<?php

declare(strict_types=1);

namespace App\Application\Security;

use App\Application\Security\ValueObjects\{RequestContext, SecurityContext};
use App\Framework\EventBus\EventBus;
use App\Framework\Waf\LayerResult;
use App\Framework\Waf\ValueObjects\Detection;
use App\Framework\Waf\ValueObjects\DetectionCollection;

/**
 * WAF Event Processor
 *
 * Processes WAF detections and converts them to OWASP Security Events
 * using the consolidated bridge system. This eliminates duplication
 * between WAF and OWASP event handling.
 */
final class WafEventProcessor
{
    public function __construct(
        private readonly WafOWASPEventBridge $bridge,
        private readonly EventBus $eventBus
    ) {
    }

    /**
     * Process WAF Layer Result and convert all detections to OWASP events
     * @return array<OWASPSecurityEvent>
     */
    public function processLayerResult(
        LayerResult $layerResult,
        RequestContext $requestContext,
        SecurityContext $securityContext
    ): array {
        $processedEvents = [];

        if ($layerResult->hasDetections()) {
            foreach ($layerResult->getDetections() as $detection) {
                $owaspEvent = $this->processDetection($detection, $requestContext, $securityContext);
                $processedEvents[] = $owaspEvent;

                // Dispatch event to the framework event bus for downstream processing
                $this->eventBus->dispatch($owaspEvent);
            }
        }

        return $processedEvents;
    }

    /**
     * Process single WAF Detection and convert to OWASP event
     */
    public function processDetection(
        Detection $detection,
        RequestContext $requestContext,
        SecurityContext $securityContext
    ): OWASPSecurityEvent {
        return $this->bridge->processWafDetection($detection, $securityContext, $requestContext);
    }

    /**
     * Process collection of WAF detections
     * @return array<OWASPSecurityEvent>
     */
    public function processDetectionCollection(
        DetectionCollection $detections,
        RequestContext $requestContext,
        SecurityContext $securityContext
    ): array {
        $processedEvents = [];

        foreach ($detections as $detection) {
            $owaspEvent = $this->processDetection($detection, $requestContext, $securityContext);
            $processedEvents[] = $owaspEvent;

            // Dispatch to event bus
            $this->eventBus->dispatch($owaspEvent);
        }

        return $processedEvents;
    }

    /**
     * Process WAF detections with batch optimization
     * @param array<LayerResult> $layerResults
     * @return array<OWASPSecurityEvent>
     */
    public function processBatch(
        array $layerResults,
        RequestContext $requestContext,
        SecurityContext $securityContext
    ): array {
        $allProcessedEvents = [];

        foreach ($layerResults as $layerResult) {
            if (! $layerResult instanceof LayerResult) {
                continue;
            }

            $processedEvents = $this->processLayerResult($layerResult, $requestContext, $securityContext);
            $allProcessedEvents = array_merge($allProcessedEvents, $processedEvents);
        }

        return $allProcessedEvents;
    }

    /**
     * Check if detection should be processed based on severity and configuration
     */
    public function shouldProcessDetection(Detection $detection): bool
    {
        // Skip false positives unless configured otherwise
        if ($detection->category === \App\Framework\Waf\DetectionCategory::FALSE_POSITIVE) {
            return false;
        }

        // Always process critical and high severity
        if ($detection->isCritical() || $detection->severity === \App\Framework\Waf\DetectionSeverity::HIGH) {
            return true;
        }

        // Process medium severity with high confidence
        if ($detection->severity === \App\Framework\Waf\DetectionSeverity::MEDIUM &&
            $detection->confidence && $detection->confidence->getValue() >= 80.0) {
            return true;
        }

        // Process OWASP Top 10 detections regardless of severity
        if ($detection->isOwaspTop10()) {
            return true;
        }

        return false;
    }

    /**
     * Create RequestContext from HTTP request data
     */
    public function createRequestContext(array $requestData): RequestContext
    {
        return new RequestContext(
            clientIp: $requestData['client_ip'] ?? 'unknown',
            userAgent: $requestData['user_agent'] ?? 'unknown',
            requestUri: $requestData['request_uri'] ?? '/',
            requestMethod: $requestData['request_method'] ?? 'GET',
            userEmail: $requestData['user_email'] ?? null,
            sessionId: $requestData['session_id'] ?? null,
            timestamp: new \DateTimeImmutable()
        );
    }

    /**
     * Create SecurityContext from security-related data
     */
    public function createSecurityContext(array $securityData): SecurityContext
    {
        return new SecurityContext(
            userId: $securityData['user_id'] ?? null,
            userRole: $securityData['user_role'] ?? 'anonymous',
            authenticationStatus: $securityData['authenticated'] ?? false,
            securityLevel: $securityData['security_level'] ?? 'standard',
            sessionMetadata: $securityData['session_metadata'] ?? []
        );
    }

    /**
     * Get processing statistics
     */
    public function getProcessingStats(): array
    {
        return [
            'bridge_version' => '1.0',
            'supported_categories' => count(\App\Framework\Waf\DetectionCategory::cases()),
            'supported_severities' => count(\App\Framework\Waf\DetectionSeverity::cases()),
            'owasp_integration' => 'enabled',
            'event_bus_integration' => 'enabled',
        ];
    }
}
