<?php

declare(strict_types=1);

namespace App\Framework\Discovery\Events;

use App\Framework\Core\ValueObjects\Byte;
use App\Framework\Core\ValueObjects\Timestamp;
use App\Framework\Discovery\Memory\LeakSeverity;

/**
 * Event fired when a memory leak is detected during discovery
 */
final readonly class MemoryLeakDetectedEvent
{
    public function __construct(
        public Byte $detectedAt,
        public Byte $growthRate,
        public LeakSeverity $severity,
        public int $windowSize,
        public ?string $context,
        public Timestamp $timestamp
    ) {
    }

    public function requiresImmediateAction(): bool
    {
        return $this->severity === LeakSeverity::CRITICAL || $this->severity === LeakSeverity::HIGH;
    }

    public function getEstimatedTimeToExhaustion(Byte $availableMemory): ?float
    {
        if ($this->growthRate->isEmpty()) {
            return null;
        }

        // Calculate time in seconds until memory exhaustion
        $timeToExhaustion = $availableMemory->toBytes() / $this->growthRate->toBytes();

        // Return null if time would be negative or unreasonably long
        return $timeToExhaustion > 0 && $timeToExhaustion < 86400 ? $timeToExhaustion : null;
    }

    public function getRecommendedActions(): array
    {
        return match ($this->severity) {
            LeakSeverity::CRITICAL => [
                'Stop processing immediately',
                'Force garbage collection',
                'Review object retention patterns',
                'Switch to STREAMING memory strategy',
                'Restart discovery with smaller batches',
            ],
            LeakSeverity::HIGH => [
                'Enable frequent cleanup cycles',
                'Reduce batch sizes',
                'Monitor object references',
                'Consider switching to CONSERVATIVE strategy',
            ],
            LeakSeverity::MEDIUM => [
                'Monitor memory usage closely',
                'Enable more frequent cleanup',
                'Review large object usage',
            ],
            LeakSeverity::LOW => [
                'Continue monitoring',
                'Consider periodic cleanup optimization',
            ]
        };
    }

    public function toArray(): array
    {
        return [
            'detected_at' => $this->detectedAt->toHumanReadable(),
            'detected_at_bytes' => $this->detectedAt->toBytes(),
            'growth_rate' => $this->growthRate->toHumanReadable(),
            'growth_rate_bytes' => $this->growthRate->toBytes(),
            'severity' => $this->severity->value,
            'window_size' => $this->windowSize,
            'context' => $this->context,
            'requires_immediate_action' => $this->requiresImmediateAction(),
            'recommended_actions' => $this->getRecommendedActions(),
            'timestamp' => $this->timestamp->toFloat(),
        ];
    }
}
