<?php

declare(strict_types=1);

namespace App\Framework\HttpClient\Examples;

use App\Framework\Core\ValueObjects\Duration;
use App\Framework\Http\Method;
use App\Framework\HttpClient\AsyncHttpClientDecorator;
use App\Framework\HttpClient\ClientRequest;
use App\Framework\HttpClient\HttpClient;

/**
 * Performance Demo: Sequential vs Parallel HTTP Requests
 */
final class AsyncHttpClientDemo
{
    public static function run(HttpClient $syncClient, AsyncHttpClientDecorator $asyncClient): void
    {
        echo "🚀 AsyncHttpClient Performance Demo\n";
        echo "===================================\n\n";

        self::demonstrateParallelRequests($syncClient, $asyncClient);
        self::demonstrateMicroservicesAggregation($asyncClient);
        self::demonstrateHealthChecks($asyncClient);
        self::demonstrateCircuitBreaker($asyncClient);
        self::demonstrateTimeoutProtection($asyncClient);
    }

    private static function demonstrateParallelRequests(HttpClient $syncClient, AsyncHttpClientDecorator $asyncClient): void
    {
        echo "📊 Test 1: Sequential vs Parallel API Calls\n";
        echo "-" . str_repeat("-", 50) . "\n";

        $requests = [
            new ClientRequest(Method::GET, 'https://jsonplaceholder.typicode.com/posts/1'),
            new ClientRequest(Method::GET, 'https://jsonplaceholder.typicode.com/posts/2'),
            new ClientRequest(Method::GET, 'https://jsonplaceholder.typicode.com/posts/3'),
            new ClientRequest(Method::GET, 'https://jsonplaceholder.typicode.com/posts/4'),
            new ClientRequest(Method::GET, 'https://jsonplaceholder.typicode.com/posts/5'),
        ];

        // Sequential execution
        echo "⏳ Executing 5 requests sequentially...\n";
        $start = microtime(true);

        $syncResults = [];
        foreach ($requests as $i => $request) {
            try {
                $syncResults[$i] = $syncClient->send($request);
            } catch (\Exception $e) {
                $syncResults[$i] = "Error: " . $e->getMessage();
            }
        }

        $syncTime = microtime(true) - $start;

        // Parallel execution
        echo "⚡ Executing 5 requests in parallel...\n";
        $start = microtime(true);

        try {
            $asyncResults = $asyncClient->sendMultiple($requests);
        } catch (\Exception $e) {
            $asyncResults = ["Error: " . $e->getMessage()];
        }

        $asyncTime = microtime(true) - $start;

        $improvement = $syncTime > 0 ? (($syncTime - $asyncTime) / $syncTime) * 100 : 0;

        echo "Sequential time: " . number_format($syncTime * 1000, 0) . "ms\n";
        echo "Parallel time:   " . number_format($asyncTime * 1000, 0) . "ms\n";
        echo "Improvement:     " . number_format($improvement, 1) . "%\n";
        echo "Successful responses: " . count(array_filter($asyncResults, fn ($r) => is_object($r))) . "/5\n\n";
    }

    private static function demonstrateMicroservicesAggregation(AsyncHttpClientDecorator $client): void
    {
        echo "🏗️  Test 2: Microservices Data Aggregation\n";
        echo "-" . str_repeat("-", 50) . "\n";

        $start = microtime(true);

        try {
            $results = $client->aggregate([
                'user_data' => new ClientRequest(Method::GET, 'https://jsonplaceholder.typicode.com/users/1'),
                'user_posts' => new ClientRequest(Method::GET, 'https://jsonplaceholder.typicode.com/users/1/posts'),
                'user_albums' => new ClientRequest(Method::GET, 'https://jsonplaceholder.typicode.com/users/1/albums'),
                'user_todos' => new ClientRequest(Method::GET, 'https://jsonplaceholder.typicode.com/users/1/todos'),
            ]);

            $time = microtime(true) - $start;

            echo "Aggregated 4 services in: " . number_format($time * 1000, 0) . "ms\n";

            $successCount = 0;
            foreach ($results as $service => $result) {
                if ($result['success']) {
                    $successCount++;
                    echo "✅ $service: Success\n";
                } else {
                    echo "❌ $service: {$result['error']}\n";
                }
            }

            echo "Success rate: $successCount/4 services\n\n";

        } catch (\Exception $e) {
            echo "❌ Aggregation failed: " . $e->getMessage() . "\n\n";
        }
    }

    private static function demonstrateHealthChecks(AsyncHttpClientDecorator $client): void
    {
        echo "🏥 Test 3: Parallel Health Checks\n";
        echo "-" . str_repeat("-", 50) . "\n";

        $start = microtime(true);

        try {
            $healthResults = $client->healthCheck([
                'json_api' => 'https://jsonplaceholder.typicode.com/posts/1',
                'github_api' => 'https://api.github.com',
                'httpbin' => 'https://httpbin.org/status/200',
                'fake_service' => 'https://nonexistent-service-12345.com',
            ], timeout: Duration::fromSeconds(5));

            $time = microtime(true) - $start;

            echo "Health check completed in: " . number_format($time * 1000, 0) . "ms\n";

            foreach ($healthResults as $service => $health) {
                $status = $health['healthy'] ? "✅ Healthy" : "❌ Unhealthy";
                $responseTime = $health['response_time_ms'] ? "{$health['response_time_ms']}ms" : "timeout";
                $error = $health['error'] ? " ({$health['error']})" : "";

                echo "$service: $status - $responseTime$error\n";
            }
            echo "\n";

        } catch (\Exception $e) {
            echo "❌ Health check failed: " . $e->getMessage() . "\n\n";
        }
    }

    private static function demonstrateCircuitBreaker(AsyncHttpClientDecorator $client): void
    {
        echo "⚡ Test 4: Circuit Breaker Pattern\n";
        echo "-" . str_repeat("-", 50) . "\n";

        $request = new ClientRequest(Method::GET, 'https://httpbin.org/status/500');

        echo "Testing circuit breaker with failing endpoint...\n";

        for ($i = 1; $i <= 7; $i++) {
            try {
                $start = microtime(true);
                $response = $client->sendWithCircuitBreaker(
                    $request,
                    'test_circuit',
                    failureThreshold: 3,
                    recoveryTimeout: Duration::fromSeconds(5)
                );
                $time = microtime(true) - $start;
                echo "Attempt $i: ✅ Success - " . number_format($time * 1000, 0) . "ms\n";

            } catch (\Exception $e) {
                $time = microtime(true) - $start;
                $message = str_contains($e->getMessage(), 'Circuit breaker') ? 'Circuit Open' : 'Request Failed';
                echo "Attempt $i: ❌ $message - " . number_format($time * 1000, 0) . "ms\n";
            }

            // Small delay between attempts
            usleep(100000); // 100ms
        }
        echo "\n";
    }

    private static function demonstrateTimeoutProtection(AsyncHttpClientDecorator $client): void
    {
        echo "⏱️  Test 5: Timeout Protection\n";
        echo "-" . str_repeat("-", 50) . "\n";

        // Test with slow endpoint
        $request = new ClientRequest(Method::GET, 'https://httpbin.org/delay/3');

        echo "Testing 1 second timeout on 3 second delay endpoint...\n";

        try {
            $start = microtime(true);
            $response = $client->sendWithTimeout($request, Duration::fromSeconds(1));
            $time = microtime(true) - $start;
            echo "✅ Request completed in: " . number_format($time * 1000, 0) . "ms\n";

        } catch (\Exception $e) {
            $time = microtime(true) - $start;
            echo "⏱️  Request timed out after: " . number_format($time * 1000, 0) . "ms\n";
            echo "Error: " . $e->getMessage() . "\n";
        }

        echo "\n";
    }
}

// Example usage:
// $syncClient = new DefaultHttpClient();
// $asyncClient = new AsyncHttpClientDecorator($syncClient, $asyncService);
// AsyncHttpClientDemo::run($syncClient, $asyncClient);
