<?php

declare(strict_types=1);

namespace App\Framework\Retry;

use App\Framework\Core\ValueObjects\Duration;
use Throwable;

/**
 * Ergebnis einer Retry-Operation mit Metadaten
 */
final readonly class RetryResult
{
    public function __construct(
        public mixed $result,
        public bool $succeeded,
        public int $totalAttempts,
        public Duration $totalDuration,
        public ?Throwable $lastException = null,
        public array $attemptHistory = []
    ) {
    }

    public static function success(
        mixed $result,
        int $attempts,
        Duration $duration,
        array $history = []
    ): self {
        return new self(
            result: $result,
            succeeded: true,
            totalAttempts: $attempts,
            totalDuration: $duration,
            attemptHistory: $history
        );
    }

    public static function failure(
        Throwable $exception,
        int $attempts,
        Duration $duration,
        array $history = []
    ): self {
        return new self(
            result: null,
            succeeded: false,
            totalAttempts: $attempts,
            totalDuration: $duration,
            lastException: $exception,
            attemptHistory: $history
        );
    }

    public function getResult(): mixed
    {
        if (! $this->succeeded) {
            throw $this->lastException ?? new \RuntimeException('Operation failed without exception');
        }

        return $this->result;
    }

    public function wasSuccessful(): bool
    {
        return $this->succeeded;
    }

    public function getAttemptCount(): int
    {
        return $this->totalAttempts;
    }

    public function getTotalDuration(): Duration
    {
        return $this->totalDuration;
    }
}
