<?php

declare(strict_types=1);

namespace App\Framework\Logging\Sampling;

use App\Framework\Logging\LogLevel;

/**
 * Sampling Configuration
 *
 * Definiert Sampling-Raten pro Log-Level.
 * Rate von 1.0 = 100% (alle Logs), 0.1 = 10%, 0.0 = keine Logs
 */
final readonly class SamplingConfig
{
    /**
     * @param array<string, float> $ratesByLevel
     */
    public function __construct(
        private array $ratesByLevel = [],
        private float $defaultRate = 1.0
    ) {
    }

    /**
     * Production-optimierte Sampling-Regeln
     */
    public static function production(): self
    {
        return new self([
            'DEBUG' => 0.0,    // Keine Debug-Logs
            'INFO' => 0.1,     // 10% Info-Logs
            'NOTICE' => 0.5,   // 50% Notice-Logs
            'WARNING' => 1.0,  // Alle Warnings
            'ERROR' => 1.0,    // Alle Errors
            'CRITICAL' => 1.0, // Alle Critical
            'ALERT' => 1.0,    // Alle Alerts
            'EMERGENCY' => 1.0, // Alle Emergency
        ]);
    }

    /**
     * Development: Alle Logs
     */
    public static function development(): self
    {
        return new self([], defaultRate: 1.0);
    }

    /**
     * Aggressive Sampling für High-Load
     */
    public static function highLoad(): self
    {
        return new self([
            'DEBUG' => 0.0,
            'INFO' => 0.01,    // 1%
            'NOTICE' => 0.1,   // 10%
            'WARNING' => 0.5,  // 50%
            'ERROR' => 1.0,
            'CRITICAL' => 1.0,
            'ALERT' => 1.0,
            'EMERGENCY' => 1.0,
        ]);
    }

    /**
     * Custom Sampling-Raten
     */
    public static function custom(array $ratesByLevel, float $defaultRate = 1.0): self
    {
        return new self($ratesByLevel, $defaultRate);
    }

    /**
     * Gibt Sampling-Rate für Level zurück
     */
    public function getRateForLevel(LogLevel $level): float
    {
        $rate = $this->ratesByLevel[$level->getName()] ?? $this->defaultRate;

        // Clamp zwischen 0.0 und 1.0
        return max(0.0, min(1.0, $rate));
    }

    /**
     * Prüft ob Level gesampelt werden soll (basierend auf Rate)
     */
    public function shouldSample(LogLevel $level): bool
    {
        $rate = $this->getRateForLevel($level);

        if ($rate >= 1.0) {
            return true;
        }

        if ($rate <= 0.0) {
            return false;
        }

        // Probabilistic sampling
        return (mt_rand() / mt_getrandmax()) < $rate;
    }

    public function toArray(): array
    {
        return [
            'rates_by_level' => $this->ratesByLevel,
            'default_rate' => $this->defaultRate,
        ];
    }
}
