<?php

declare(strict_types=1);

namespace App\Framework\ErrorHandling;

use App\Framework\Exception\SecurityException;
use App\Framework\Exception\ErrorHandlerContext;
use App\Framework\Http\MiddlewareContext;
use App\Framework\Logging\Logger;
use Throwable;

/**
 * Spezialisierte Klasse für Security-Event-Handling und OWASP-konformes Logging
 */
final readonly class SecurityEventHandler
{
    public function __construct(
        private SecurityEventLogger $securityLogger,
        private ?SecurityAlertManager $alertManager = null
    ) {}

    /**
     * Behandelt Security-Exception und führt entsprechendes Logging durch
     */
    public function handleSecurityException(
        SecurityException $exception,
        ?MiddlewareContext $context = null
    ): void {
        try {
            // Erstelle ErrorHandlerContext für OWASP-Format
            $errorHandlerContext = ErrorHandlerContext::fromException($exception, $context);

            // Führe Security-Logging durch
            $this->securityLogger->logSecurityEvent($exception, $errorHandlerContext);

            // Sende Alert falls erforderlich
            if ($exception->requiresAlert()) {
                $this->handleSecurityAlert($exception, $errorHandlerContext);
            }

        } catch (Throwable $loggingError) {
            // Fallback-Logging: Niemals Security-Events verlieren
            $this->handleLoggingFailure($exception, $loggingError);
        }
    }

    /**
     * Prüft ob Exception eine SecurityException ist und behandelt sie entsprechend
     */
    public function handleIfSecurityException(
        Throwable $exception,
        ?MiddlewareContext $context = null
    ): bool {
        if (!$exception instanceof SecurityException) {
            return false;
        }

        $this->handleSecurityException($exception, $context);
        return true;
    }

    /**
     * Behandelt Security-Alerts
     */
    private function handleSecurityAlert(
        SecurityException $exception,
        ErrorHandlerContext $context
    ): void {
        if ($this->alertManager) {
            $this->alertManager->sendAlert($exception, $context);
        } else {
            // Fallback: Logge als kritisches Event
            $this->securityLogger->logCriticalAlert($exception, $context);
        }
    }

    /**
     * Behandelt Fehler beim Security-Logging (Fallback)
     */
    private function handleLoggingFailure(
        SecurityException $originalException,
        Throwable $loggingError
    ): void {
        // Niemals Security-Events verlieren - verwende error_log als Fallback
        $fallbackMessage = sprintf(
            'SECURITY_AUDIT_FAILURE: Failed to log security event %s - %s',
            $originalException->getSecurityEvent()->getEventIdentifier(),
            $loggingError->getMessage()
        );

        error_log($fallbackMessage);

        // Versuche minimales Security-Log
        try {
            $minimalLog = [
                'datetime' => date('c'),
                'event' => $originalException->getSecurityEvent()->getEventIdentifier(),
                'description' => $originalException->getSecurityEvent()->getDescription(),
                'level' => 'FATAL',
                'audit_failure' => true,
                'original_error' => $loggingError->getMessage()
            ];

            error_log('SECURITY_EVENT_FALLBACK: ' . json_encode($minimalLog));

        } catch (Throwable $criticalError) {
            // Absoluter Fallback
            error_log('CRITICAL_SECURITY_AUDIT_FAILURE: Unable to log security event');
        }
    }

    /**
     * Factory-Methode mit Standard-Konfiguration
     */
    public static function createDefault(?Logger $logger = null): self
    {
        $securityLogger = new SecurityEventLogger($logger);
        $alertManager = null; // Kann später konfiguriert werden

        return new self($securityLogger, $alertManager);
    }
}
