<?php

declare(strict_types=1);

namespace App\Framework\MachineLearning\ModelManagement;

use App\Framework\Core\ValueObjects\Duration;

/**
 * ML Model Management Configuration
 *
 * Typsichere Konfiguration für das ML-Management System mit Value Objects.
 *
 * Features:
 * - Drift Detection Konfiguration
 * - Performance Monitoring Settings
 * - Auto-Tuning Configuration
 * - Cache Strategien
 * - Alert Thresholds
 */
final readonly class MLConfig
{
    public function __construct(
        public bool $monitoringEnabled = true,
        public float $driftThreshold = 0.15,
        public Duration $performanceWindow = new Duration(86400), // 24 hours
        public bool $autoTuningEnabled = false,
        public Duration $predictionCacheTtl = new Duration(3600), // 1 hour
        public Duration $modelCacheTtl = new Duration(7200), // 2 hours
        public Duration $baselineUpdateInterval = new Duration(86400), // 24 hours
        public int $minPredictionsForDrift = 100,
        public float $confidenceAlertThreshold = 0.65,
        public float $accuracyAlertThreshold = 0.75
    ) {
        // Validation
        if ($driftThreshold < 0.0 || $driftThreshold > 1.0) {
            throw new \InvalidArgumentException('Drift threshold must be between 0.0 and 1.0');
        }

        if ($confidenceAlertThreshold < 0.0 || $confidenceAlertThreshold > 1.0) {
            throw new \InvalidArgumentException('Confidence alert threshold must be between 0.0 and 1.0');
        }

        if ($accuracyAlertThreshold < 0.0 || $accuracyAlertThreshold > 1.0) {
            throw new \InvalidArgumentException('Accuracy alert threshold must be between 0.0 and 1.0');
        }

        if ($minPredictionsForDrift < 1) {
            throw new \InvalidArgumentException('Minimum predictions for drift must be at least 1');
        }
    }

    /**
     * Create configuration from environment
     */
    public static function fromEnvironment(array $env = []): self
    {
        $getEnv = fn(string $key, mixed $default = null): mixed => $env[$key] ?? $_ENV[$key] ?? $default;

        return new self(
            monitoringEnabled: filter_var($getEnv('ML_MONITORING_ENABLED', true), FILTER_VALIDATE_BOOLEAN),
            driftThreshold: (float) $getEnv('ML_DRIFT_THRESHOLD', 0.15),
            performanceWindow: Duration::fromHours((int) $getEnv('ML_PERFORMANCE_WINDOW_HOURS', 24)),
            autoTuningEnabled: filter_var($getEnv('ML_AUTO_TUNING_ENABLED', false), FILTER_VALIDATE_BOOLEAN),
            predictionCacheTtl: Duration::fromSeconds((int) $getEnv('ML_PREDICTION_CACHE_TTL', 3600)),
            modelCacheTtl: Duration::fromSeconds((int) $getEnv('ML_MODEL_CACHE_TTL', 7200)),
            baselineUpdateInterval: Duration::fromSeconds((int) $getEnv('ML_BASELINE_UPDATE_INTERVAL', 86400)),
            minPredictionsForDrift: (int) $getEnv('ML_MIN_PREDICTIONS_FOR_DRIFT', 100),
            confidenceAlertThreshold: (float) $getEnv('ML_CONFIDENCE_ALERT_THRESHOLD', 0.65),
            accuracyAlertThreshold: (float) $getEnv('ML_ACCURACY_ALERT_THRESHOLD', 0.75)
        );
    }

    /**
     * Production-optimized configuration
     */
    public static function production(): self
    {
        return new self(
            monitoringEnabled: true,
            driftThreshold: 0.15,
            performanceWindow: Duration::fromHours(24),
            autoTuningEnabled: true,
            predictionCacheTtl: Duration::fromHours(1),
            modelCacheTtl: Duration::fromHours(2),
            baselineUpdateInterval: Duration::fromHours(24),
            minPredictionsForDrift: 100,
            confidenceAlertThreshold: 0.65,
            accuracyAlertThreshold: 0.75
        );
    }

    /**
     * Development configuration
     */
    public static function development(): self
    {
        return new self(
            monitoringEnabled: true,
            driftThreshold: 0.20,
            performanceWindow: Duration::fromHours(1),
            autoTuningEnabled: false,
            predictionCacheTtl: Duration::fromMinutes(5),
            modelCacheTtl: Duration::fromMinutes(10),
            baselineUpdateInterval: Duration::fromHours(1),
            minPredictionsForDrift: 10,
            confidenceAlertThreshold: 0.60,
            accuracyAlertThreshold: 0.70
        );
    }

    /**
     * Testing configuration
     */
    public static function testing(): self
    {
        return new self(
            monitoringEnabled: false,
            driftThreshold: 0.25,
            performanceWindow: Duration::fromMinutes(5),
            autoTuningEnabled: false,
            predictionCacheTtl: Duration::fromSeconds(10),
            modelCacheTtl: Duration::fromSeconds(10),
            baselineUpdateInterval: Duration::fromMinutes(5),
            minPredictionsForDrift: 5,
            confidenceAlertThreshold: 0.50,
            accuracyAlertThreshold: 0.60
        );
    }

    /**
     * Check if drift detection is enabled
     */
    public function isDriftDetectionEnabled(): bool
    {
        return $this->monitoringEnabled && $this->minPredictionsForDrift > 0;
    }

    /**
     * Check if a drift value exceeds threshold
     */
    public function isDriftDetected(float $driftValue): bool
    {
        return $driftValue > $this->driftThreshold;
    }

    /**
     * Check if confidence is below alert threshold
     */
    public function isLowConfidence(float $confidence): bool
    {
        return $confidence < $this->confidenceAlertThreshold;
    }

    /**
     * Check if accuracy is below alert threshold
     */
    public function isLowAccuracy(float $accuracy): bool
    {
        return $accuracy < $this->accuracyAlertThreshold;
    }
}
