<?php

declare(strict_types=1);

namespace App\Framework\HttpClient\Middleware;

use App\Framework\Core\ValueObjects\Duration;
use App\Framework\DateTime\Timer;
use App\Framework\HttpClient\ClientRequest;
use App\Framework\HttpClient\ClientResponse;
use App\Framework\HttpClient\HttpClientMiddleware;

final readonly class RetryMiddleware implements HttpClientMiddleware
{
    public function __construct(
        private Timer $timer,
        private int   $maxRetries = 3,
        private float $baseDelay = 1.0,
        private array $retryableStatuses = [500, 502, 503, 504]
    ) {
    }

    public function __invoke(ClientRequest $request, callable $next): ClientResponse
    {
        $attempt = 0;

        while ($attempt <= $this->maxRetries) {
            try {
                $response = $next($request);

                // Erfolgreich oder nicht wiederholbar
                if ($response->isSuccessful() || ! in_array($response->status->value, $this->retryableStatuses)) {
                    return $response;
                }

                // Letzter Versuch
                if ($attempt === $this->maxRetries) {
                    return $response;
                }

                // Exponential backoff
                $delay = $this->baseDelay * (2 ** $attempt);
                $this->timer->sleep(Duration::fromSeconds($delay));

            } catch (\Throwable $e) {
                if ($attempt === $this->maxRetries) {
                    throw $e;
                }

                $delay = $this->baseDelay * (2 ** $attempt);
                $this->timer->sleep(Duration::fromSeconds($delay));
            }

            $attempt++;
        }

        return $next($request);
    }
}
