<?php

declare(strict_types=1);

namespace App\Framework\Health\ValueObjects;

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

/**
 * Value Object for response time measurements
 * Uses Duration as foundation and adds health-check specific functionality
 */
final readonly class ResponseTime
{
    public function __construct(
        public Duration $duration
    ) {
        // Duration already validates non-negative values
        if ($duration->toSeconds() > 300) { // 5 minutes max for health checks
            throw new InvalidArgumentException('Response time cannot exceed 5 minutes for health checks');
        }
    }

    public static function fromDuration(Duration $duration): self
    {
        return new self($duration);
    }

    public static function fromSeconds(float $seconds): self
    {
        return new self(Duration::fromSeconds($seconds));
    }

    public static function fromMilliseconds(float $milliseconds): self
    {
        return new self(Duration::fromMilliseconds($milliseconds));
    }

    public static function fromStartTime(float $startTime): self
    {
        $endTime = microtime(true);
        $duration = Duration::fromSeconds($endTime - $startTime);

        return new self($duration);
    }

    public static function measure(callable $operation): self
    {
        $startTime = microtime(true);
        $operation();
        $endTime = microtime(true);

        return new self(Duration::fromSeconds($endTime - $startTime));
    }

    public static function zero(): self
    {
        return new self(Duration::zero());
    }

    // Performance level assessment for health checks
    public function isFast(): bool
    {
        return $this->duration->toMilliseconds() < 100; // < 100ms
    }

    public function isAcceptable(): bool
    {
        return $this->duration->toMilliseconds() < 500; // < 500ms
    }

    public function isSlow(): bool
    {
        $ms = $this->duration->toMilliseconds();

        return $ms >= 500 && $ms < 2000; // 500ms-2s
    }

    public function isVerySlow(): bool
    {
        return $this->duration->toMilliseconds() >= 2000; // >= 2s
    }

    public function getPerformanceLevel(): ResponseTimeLevel
    {
        return match (true) {
            $this->isFast() => ResponseTimeLevel::FAST,
            $this->isAcceptable() => ResponseTimeLevel::ACCEPTABLE,
            $this->isSlow() => ResponseTimeLevel::SLOW,
            default => ResponseTimeLevel::VERY_SLOW
        };
    }

    public function exceedsThreshold(Duration $threshold): bool
    {
        return $this->duration->greaterThan($threshold);
    }

    public function isWithinThreshold(Duration $threshold): bool
    {
        return ! $this->exceedsThreshold($threshold);
    }

    // Delegate common operations to Duration
    public function toString(): string
    {
        return $this->duration->toHumanReadable();
    }

    public function __toString(): string
    {
        return $this->toString();
    }

    public function toArray(): array
    {
        return [
            'milliseconds' => $this->duration->toMilliseconds(),
            'seconds' => $this->duration->toSeconds(),
            'formatted' => $this->toString(),
            'level' => $this->getPerformanceLevel()->value,
            'is_fast' => $this->isFast(),
            'is_acceptable' => $this->isAcceptable(),
            'is_slow' => $this->isSlow(),
            'is_very_slow' => $this->isVerySlow(),
        ];
    }

    public function equals(self $other): bool
    {
        return $this->duration->equals($other->duration);
    }

    public function isSlowerThan(self $other): bool
    {
        return $this->duration->greaterThan($other->duration);
    }

    public function isFasterThan(self $other): bool
    {
        return $this->duration->lessThan($other->duration);
    }
}
