<?php

/*
 * This file is part of the official PHP MCP SDK.
 *
 * A collaboration between Symfony and the PHP Foundation.
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/**
 * HTTP Client Communication Example.
 *
 * This example demonstrates server-to-client communication over HTTP:
 * - Logging notifications
 * - Progress notifications (via SSE streaming)
 * - Sampling requests (mocked LLM response)
 *
 * Usage:
 *   1. Start the server: php -S 127.0.0.1:8000 examples/server/client-communication/server.php
 *   2. Run this script: php examples/client/http_client_communication.php
 *
 * Note: PHP's built-in server works for listing tools, calling tools, and receiving
 * progress/logging notifications. However, sampling requires a concurrent-capable server
 * (e.g., Symfony CLI, PHP-FPM) since the server must process the client's sampling
 * response while the original tool request is still pending.
 *
 * Eg. symfony serve --passthru=examples/server/client-communication/server.php --no-tls
 */

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

use Mcp\Client;
use Mcp\Client\Handler\Notification\LoggingNotificationHandler;
use Mcp\Client\Handler\Request\SamplingCallbackInterface;
use Mcp\Client\Handler\Request\SamplingRequestHandler;
use Mcp\Client\Transport\HttpTransport;
use Mcp\Schema\ClientCapabilities;
use Mcp\Schema\Content\TextContent;
use Mcp\Schema\Enum\Role;
use Mcp\Schema\Notification\LoggingMessageNotification;
use Mcp\Schema\Request\CreateSamplingMessageRequest;
use Mcp\Schema\Result\CreateSamplingMessageResult;

$endpoint = 'http://127.0.0.1:8000';

$loggingNotificationHandler = new LoggingNotificationHandler(static function (LoggingMessageNotification $n) {
    echo "[LOG {$n->level->value}] {$n->data}\n";
});

$samplingRequestHandler = new SamplingRequestHandler(new class implements SamplingCallbackInterface {
    public function __invoke(CreateSamplingMessageRequest $request): CreateSamplingMessageResult
    {
        echo "[SAMPLING] Server requested LLM sampling (max {$request->maxTokens} tokens)\n";

        $mockResponse = 'Based on the incident analysis, I recommend: 1) Activate the on-call team, '.
            '2) Isolate affected systems, 3) Begin root cause analysis, 4) Prepare stakeholder communication.';

        return new CreateSamplingMessageResult(
            role: Role::Assistant,
            content: new TextContent($mockResponse),
            model: 'mock-gpt-4',
            stopReason: 'endTurn',
        );
    }
});

$client = Client::builder()
    ->setClientInfo('HTTP Client Communication Test', '1.0.0')
    ->setInitTimeout(30)
    ->setRequestTimeout(120)
    ->setCapabilities(new ClientCapabilities(sampling: true))
    ->addNotificationHandler($loggingNotificationHandler)
    ->addRequestHandler($samplingRequestHandler)
    ->build();

$transport = new HttpTransport(endpoint: $endpoint);

try {
    echo "Connecting to MCP server at {$endpoint}...\n";
    $client->connect($transport);

    $serverInfo = $client->getServerInfo();
    echo 'Connected to: '.($serverInfo->name ?? 'unknown')."\n\n";

    echo "Available tools:\n";
    $toolsResult = $client->listTools();
    foreach ($toolsResult->tools as $tool) {
        echo "  - {$tool->name}\n";
    }
    echo "\n";

    echo "Calling 'run_dataset_quality_checks'...\n\n";
    $result = $client->callTool(
        name: 'run_dataset_quality_checks',
        arguments: ['dataset' => 'sales_transactions_q4'],
        onProgress: static function (float $progress, ?float $total, ?string $message) {
            $percent = $total > 0 ? round(($progress / $total) * 100) : '?';
            echo "[PROGRESS {$percent}%] {$message}\n";
        }
    );

    echo "\nResult:\n";
    foreach ($result->content as $content) {
        if ($content instanceof TextContent) {
            echo $content->text."\n";
        }
    }

    echo "\nCalling 'coordinate_incident_response'...\n\n";
    $result = $client->callTool(
        name: 'coordinate_incident_response',
        arguments: ['incidentTitle' => 'Database connection pool exhausted'],
        onProgress: static function (float $progress, ?float $total, ?string $message) {
            $percent = $total > 0 ? round(($progress / $total) * 100) : '?';
            echo "[PROGRESS {$percent}%] {$message}\n";
        }
    );

    echo "\nResult:\n";
    foreach ($result->content as $content) {
        if ($content instanceof TextContent) {
            echo $content->text."\n";
        }
    }
} catch (Throwable $e) {
    echo "Error: {$e->getMessage()}\n";
    echo $e->getTraceAsString()."\n";
} finally {
    $client->disconnect();
}