<?php

declare(strict_types=1);

namespace App\Framework\Config;

use App\Framework\Core\AttributeMapper;

final readonly class DiscoveryConfig
{
    /**
     * Konstanten für Standardwerte
     */
    public const int DEFAULT_CHUNK_SIZE = 100;
    public const int DEFAULT_MAX_RETRIES = 3;
    public const float DEFAULT_MEMORY_THRESHOLD_HIGH = 0.8;
    public const float DEFAULT_MEMORY_THRESHOLD_CRITICAL = 0.9;
    public const int DEFAULT_WORKER_COUNT = 4;
    public const int DEFAULT_CACHE_TTL = 3600; // 1 hour

    /**
     * @param array<AttributeMapper> $attributeMappers
     * @param array<class-string> $targetInterfaces
     */
    public function __construct(
        // Basis-Konfiguration
        public bool $useCache = true,
        public bool $showProgress = false,
        public bool $useContextAwareInitializers = false,
        public bool $enableCircuitBreaker = true,
        public array $attributeMappers = [],
        public array $targetInterfaces = [],

        // Memory-Management-Konfiguration
        public bool $enableAdaptiveChunking = true,
        public int $chunkSize = self::DEFAULT_CHUNK_SIZE,
        public float $memoryThresholdHigh = self::DEFAULT_MEMORY_THRESHOLD_HIGH,
        public float $memoryThresholdCritical = self::DEFAULT_MEMORY_THRESHOLD_CRITICAL,

        // Asynchrone Verarbeitung
        public bool $enableAsyncProcessing = false,
        public ?int $workerCount = null, // null = automatisch bestimmen
        public bool $enableWorkloadBalancing = true,

        // Fehlerbehandlung
        public int $maxRetries = self::DEFAULT_MAX_RETRIES,
        public string $logLevel = 'info', // 'debug', 'info', 'warning', 'error'
        public bool $continueOnError = true,

        // Cache-Validierung
        public int $cacheTtl = self::DEFAULT_CACHE_TTL,
        public bool $enableChecksumValidation = true,
        public bool $enableCacheWarming = false,
    ) {
        // Validiere Werte
        $this->validateConfig();
    }

    /**
     * Validiert die Konfigurationswerte
     * @throws \InvalidArgumentException wenn ungültige Werte gefunden werden
     */
    private function validateConfig(): void
    {
        // Validiere numerische Werte
        if ($this->chunkSize < 1) {
            throw new \InvalidArgumentException('Chunk size must be at least 1');
        }

        if ($this->memoryThresholdHigh <= 0 || $this->memoryThresholdHigh >= 1) {
            throw new \InvalidArgumentException('Memory threshold high must be between 0 and 1');
        }

        if ($this->memoryThresholdCritical <= $this->memoryThresholdHigh || $this->memoryThresholdCritical >= 1) {
            throw new \InvalidArgumentException('Memory threshold critical must be between memory threshold high and 1');
        }

        if ($this->workerCount !== null && $this->workerCount < 1) {
            throw new \InvalidArgumentException('Worker count must be at least 1');
        }

        if ($this->maxRetries < 0) {
            throw new \InvalidArgumentException('Max retries must be at least 0');
        }

        if ($this->cacheTtl < 0) {
            throw new \InvalidArgumentException('Cache TTL must be at least 0');
        }

        // Validiere Enum-Werte
        $validLogLevels = ['debug', 'info', 'warning', 'error'];
        if (! in_array($this->logLevel, $validLogLevels, true)) {
            throw new \InvalidArgumentException('Log level must be one of: ' . implode(', ', $validLogLevels));
        }
    }

    /**
     * Erstellt Konfiguration aus Umgebungsvariablen
     */
    public static function fromEnvironment(Environment $env): self
    {
        return new self(
            // Basis-Konfiguration
            useCache: $env->getBool('DISCOVERY_USE_CACHE', true),
            showProgress: $env->getBool('DISCOVERY_SHOW_PROGRESS', false),
            useContextAwareInitializers: $env->getBool('ENABLE_CONTEXT_AWARE_INITIALIZERS', false),
            enableCircuitBreaker: $env->getBool('DISCOVERY_ENABLE_CIRCUIT_BREAKER', true),
            attributeMappers: [], // Will be set to defaults in DiscoveryServiceBootstrapper
            targetInterfaces: [], // Will be set to defaults in DiscoveryServiceBootstrapper

            // Memory-Management-Konfiguration
            enableAdaptiveChunking: $env->getBool('DISCOVERY_ENABLE_ADAPTIVE_CHUNKING', true),
            chunkSize: $env->getInt('DISCOVERY_CHUNK_SIZE', self::DEFAULT_CHUNK_SIZE),
            memoryThresholdHigh: $env->getFloat('DISCOVERY_MEMORY_THRESHOLD_HIGH', self::DEFAULT_MEMORY_THRESHOLD_HIGH),
            memoryThresholdCritical: $env->getFloat('DISCOVERY_MEMORY_THRESHOLD_CRITICAL', self::DEFAULT_MEMORY_THRESHOLD_CRITICAL),

            // Asynchrone Verarbeitung
            enableAsyncProcessing: $env->getBool('DISCOVERY_ENABLE_ASYNC', false),
            workerCount: $env->has('DISCOVERY_WORKER_COUNT') ? $env->getInt('DISCOVERY_WORKER_COUNT') : null,
            enableWorkloadBalancing: $env->getBool('DISCOVERY_ENABLE_WORKLOAD_BALANCING', true),

            // Fehlerbehandlung
            maxRetries: $env->getInt('DISCOVERY_MAX_RETRIES', self::DEFAULT_MAX_RETRIES),
            logLevel: $env->getString('DISCOVERY_LOG_LEVEL', 'info'),
            continueOnError: $env->getBool('DISCOVERY_CONTINUE_ON_ERROR', true),

            // Cache-Validierung
            cacheTtl: $env->getInt('DISCOVERY_CACHE_TTL', self::DEFAULT_CACHE_TTL),
            enableChecksumValidation: $env->getBool('DISCOVERY_ENABLE_CHECKSUM_VALIDATION', true),
            enableCacheWarming: $env->getBool('DISCOVERY_ENABLE_CACHE_WARMING', false)
        );
    }

    /**
     * Erstellt eine Entwicklungskonfiguration mit detailliertem Logging und Robustheit
     */
    public static function development(): self
    {
        return new self(
            // Basis-Konfiguration
            useCache: true,
            showProgress: true,
            useContextAwareInitializers: true,
            enableCircuitBreaker: true,

            // Memory-Management-Konfiguration
            enableAdaptiveChunking: true,
            chunkSize: 50, // Kleinere Chunks für bessere Responsiveness

            // Asynchrone Verarbeitung
            enableAsyncProcessing: false, // Synchron für einfacheres Debugging

            // Fehlerbehandlung
            maxRetries: 3,
            logLevel: 'debug', // Detailliertes Logging
            continueOnError: true,

            // Cache-Validierung
            cacheTtl: 1800, // 30 Minuten (kürzere Zeit für Entwicklung)
            enableChecksumValidation: true,
            enableCacheWarming: false
        );
    }

    /**
     * Erstellt eine Produktionskonfiguration mit optimaler Performance
     */
    public static function production(): self
    {
        return new self(
            // Basis-Konfiguration
            useCache: true,
            showProgress: false,
            useContextAwareInitializers: true,
            enableCircuitBreaker: true,

            // Memory-Management-Konfiguration
            enableAdaptiveChunking: true,
            chunkSize: 100,

            // Asynchrone Verarbeitung
            enableAsyncProcessing: true, // Asynchron für bessere Performance
            workerCount: null, // Automatisch bestimmen
            enableWorkloadBalancing: true,

            // Fehlerbehandlung
            maxRetries: 2,
            logLevel: 'info',
            continueOnError: true,

            // Cache-Validierung
            cacheTtl: 86400, // 24 Stunden
            enableChecksumValidation: true,
            enableCacheWarming: true
        );
    }

    /**
     * Erstellt eine Konfiguration für Umgebungen mit wenig Speicher
     */
    public static function lowMemory(): self
    {
        return new self(
            // Basis-Konfiguration
            useCache: true,
            showProgress: false,
            useContextAwareInitializers: false, // Reduziert Speicherverbrauch
            enableCircuitBreaker: true,

            // Memory-Management-Konfiguration
            enableAdaptiveChunking: true,
            chunkSize: 25, // Sehr kleine Chunks
            memoryThresholdHigh: 0.7, // Früher eingreifen
            memoryThresholdCritical: 0.8,

            // Asynchrone Verarbeitung
            enableAsyncProcessing: false, // Synchron für weniger Speicherverbrauch

            // Fehlerbehandlung
            maxRetries: 1, // Minimale Retries
            logLevel: 'warning', // Minimales Logging
            continueOnError: true,

            // Cache-Validierung
            cacheTtl: 172800, // 48 Stunden (längere Cache-Zeit)
            enableChecksumValidation: false, // Deaktiviert für weniger Speicherverbrauch
            enableCacheWarming: false
        );
    }

    /**
     * Erstellt eine Konfiguration für Hochleistungsserver
     */
    public static function highPerformance(): self
    {
        return new self(
            // Basis-Konfiguration
            useCache: true,
            showProgress: false,
            useContextAwareInitializers: true,
            enableCircuitBreaker: true,

            // Memory-Management-Konfiguration
            enableAdaptiveChunking: true,
            chunkSize: 200, // Größere Chunks

            // Asynchrone Verarbeitung
            enableAsyncProcessing: true,
            workerCount: 8, // Feste Anzahl für optimale Parallelisierung
            enableWorkloadBalancing: true,

            // Fehlerbehandlung
            maxRetries: 2,
            logLevel: 'info',
            continueOnError: true,

            // Cache-Validierung
            cacheTtl: 43200, // 12 Stunden
            enableChecksumValidation: true,
            enableCacheWarming: true
        );
    }
}
