<?php

declare(strict_types=1);

namespace App\Framework\Performance\ValueObjects;

/**
 * GC Status Value Object
 *
 * Immutable representation of PHP garbage collection status.
 * Wraps gc_status() array into type-safe Value Object.
 */
final readonly class GcStatus
{
    /**
     * @param int $runs Number of times the GC algorithm has run
     * @param int $collected Number of cycles collected
     * @param int $threshold GC threshold (number of root buffers before GC runs)
     * @param int $roots Current number of root buffers
     * @param bool $running Whether GC is currently running
     */
    public function __construct(
        public int $runs,
        public int $collected,
        public int $threshold,
        public int $roots,
        public bool $running = false
    ) {
    }

    /**
     * Calculate collection efficiency
     *
     * Returns ratio of collected cycles to runs.
     * Higher values indicate more effective GC.
     */
    public function getCollectionEfficiency(): float
    {
        if ($this->runs === 0) {
            return 0.0;
        }

        return $this->collected / $this->runs;
    }

    /**
     * Calculate threshold utilization
     *
     * Returns ratio of current roots to threshold.
     * Values close to 1.0 indicate GC is about to run.
     */
    public function getThresholdUtilization(): float
    {
        if ($this->threshold === 0) {
            return 0.0;
        }

        return $this->roots / $this->threshold;
    }

    /**
     * Check if GC threshold is close to being reached
     */
    public function isNearThreshold(float $percentage = 0.9): bool
    {
        return $this->getThresholdUtilization() >= $percentage;
    }

    /**
     * Check if GC is performing well
     *
     * GC is considered healthy if:
     * - It has run at least once
     * - Collection efficiency is reasonable (> 0)
     * - Not constantly near threshold
     */
    public function isHealthy(): bool
    {
        return $this->runs > 0
            && $this->getCollectionEfficiency() > 0
            && !$this->isNearThreshold(0.95);
    }

    /**
     * Convert to array for serialization
     */
    public function toArray(): array
    {
        return [
            'runs' => $this->runs,
            'collected' => $this->collected,
            'threshold' => $this->threshold,
            'roots' => $this->roots,
            'running' => $this->running,
            'collection_efficiency' => $this->getCollectionEfficiency(),
            'threshold_utilization' => $this->getThresholdUtilization(),
            'is_healthy' => $this->isHealthy(),
        ];
    }

    /**
     * Create from gc_status() array
     */
    public static function fromGcStatus(array $status): self
    {
        return new self(
            runs: $status['runs'] ?? 0,
            collected: $status['collected'] ?? 0,
            threshold: $status['threshold'] ?? 10001,
            roots: $status['roots'] ?? 0,
            running: $status['running'] ?? false
        );
    }

    /**
     * Get current GC status
     */
    public static function current(): self
    {
        return self::fromGcStatus(gc_status());
    }
}
