<?php

declare(strict_types=1);

namespace App\Framework\Analytics\Listeners;

use App\Framework\Analytics\AnalyticsCategory;
use App\Framework\Analytics\AnalyticsCollector;
use App\Framework\Analytics\Events\SecurityEvent;
use App\Framework\Exception\SecurityEvent\SecurityEventInterface;

/**
 * Security-Analytics Listener
 *
 * Hört auf Security-Events und konvertiert sie zu Analytics-Daten
 * ohne direkte Kopplung zwischen Security und Analytics
 */
final readonly class SecurityAnalyticsListener
{
    public function __construct(
        private AnalyticsCollector $analyticsCollector,
        private bool $enabled = true
    ) {
    }

    /**
     * Behandelt Security-Events und konvertiert sie zu Analytics
     */
    public function handleSecurityEvent(SecurityEventInterface $securityEvent): void
    {
        if (! $this->enabled) {
            return;
        }

        // Konvertiere Security-Event zu Analytics-Event
        $analyticsEvent = $this->convertToAnalyticsEvent($securityEvent);

        // Tracke das Event im Analytics-System
        $this->analyticsCollector->trackAction(
            action: $analyticsEvent->eventType,
            category: AnalyticsCategory::SECURITY,
            properties: $analyticsEvent->properties
        );

        // Dispatch Analytics-Event für weitere Verarbeitung
        $this->dispatchAnalyticsEvent($analyticsEvent);
    }

    /**
     * Konvertiert Security-Event zu Analytics-Event
     */
    private function convertToAnalyticsEvent(SecurityEventInterface $securityEvent): SecurityEvent
    {
        $properties = array_merge($securityEvent->toArray(), [
            'severity' => $securityEvent->getLogLevel()->value,
            'category' => $securityEvent->getCategory(),
            'requires_alert' => $securityEvent->requiresAlert(),
            'timestamp' => microtime(true),
        ]);

        // Entferne potentiell sensitive Daten
        $properties = $this->sanitizeProperties($properties);

        return new SecurityEvent(
            eventType: $this->mapEventType($securityEvent),
            category: $securityEvent->getCategory(),
            severity: $securityEvent->getLogLevel()->value,
            properties: $properties
        );
    }

    /**
     * Mappt Security-Event-Typen zu Analytics-Event-Typen
     */
    private function mapEventType(SecurityEventInterface $securityEvent): string
    {
        $eventId = $securityEvent->getEventIdentifier();

        return match (true) {
            str_contains($eventId, 'sql_injection') => 'security_sql_injection_attempt',
            str_contains($eventId, 'xss') => 'security_xss_attempt',
            str_contains($eventId, 'path_traversal') => 'security_path_traversal_attempt',
            str_contains($eventId, 'command_injection') => 'security_command_injection_attempt',
            str_contains($eventId, 'rate_limit') => 'security_rate_limit_exceeded',
            str_contains($eventId, 'bot_detection') => 'security_bot_detected',
            default => 'security_general_threat'
        };
    }

    /**
     * Entfernt sensitive Daten aus Properties
     */
    private function sanitizeProperties(array $properties): array
    {
        $sensitiveKeys = [
            'password', 'token', 'api_key', 'session', 'credit_card',
            'ssn', 'personal_id', 'auth_token', 'bearer', 'cookie',
        ];

        foreach ($properties as $key => $value) {
            $keyLower = strtolower($key);

            foreach ($sensitiveKeys as $sensitiveKey) {
                if (str_contains($keyLower, $sensitiveKey)) {
                    $properties[$key] = '[REDACTED]';

                    break;
                }
            }
        }

        return $properties;
    }

    /**
     * Dispatcht Analytics-Event für weitere Verarbeitung
     */
    private function dispatchAnalyticsEvent(SecurityEvent $event): void
    {
        // Hier könnte ein EventDispatcher verwendet werden
        // Falls das Event-System erweitert werden soll

        // Für jetzt: Einfache Implementierung ohne weitere Events
        // Das Event ist bereits im Analytics-System getrackt
    }
}
