<?php

declare(strict_types=1);

namespace App\Framework\DDoS;

use App\Framework\DateTime\Clock;
use App\Framework\DDoS\Analysis\GeoAnomalyDetector;
use App\Framework\DDoS\Analysis\TrafficPatternAnalyzer;
use App\Framework\DDoS\Components\AttackPatternDetector;
use App\Framework\DDoS\Components\RequestAnalyzer;
use App\Framework\DDoS\Components\ServiceHealthAnalyzer;
use App\Framework\DDoS\Components\ThreatLevelCalculator;
use App\Framework\DDoS\Components\WafAnalysisAdapter;
use App\Framework\DDoS\Response\AdaptiveResponseSystem;
use App\Framework\DDoS\Response\ValueObjects\DDoSResponse;
use App\Framework\DDoS\ValueObjects\DDoSAssessment;
use App\Framework\DDoS\ValueObjects\ThreatLevel;
use App\Framework\ErrorHandling\SecurityEventLogger;
use App\Framework\Http\HttpRequest;
use App\Framework\Http\IpAddress;
use App\Framework\Logging\Logger;
use App\Framework\Performance\PerformanceService;

/**
 * DDoS Protection Engine - Orchestrates security modules for DDoS protection
 *
 * This engine acts as an intelligent coordinator that leverages multiple
 * specialized components to detect and respond to DDoS attacks.
 */
final class DDoSProtectionEngine
{
    private const float HIGH_THRESHOLD = 0.7;

    public function __construct(
        private readonly TrafficPatternAnalyzer $trafficAnalyzer,
        private readonly GeoAnomalyDetector $geoDetector,
        private readonly AdaptiveResponseSystem $responseSystem,
        private readonly SecurityEventLogger $securityLogger,
        private readonly PerformanceService $performance,
        private readonly Logger $logger,
        private readonly Clock $clock,
        private readonly DDoSConfig $config,
        // New modular components
        private readonly ThreatLevelCalculator $threatCalculator,
        private readonly AttackPatternDetector $patternDetector,
        private readonly RequestAnalyzer $requestAnalyzer,
        private readonly ServiceHealthAnalyzer $serviceAnalyzer,
        private readonly WafAnalysisAdapter $wafAnalyzer
    ) {
    }

    /**
     * Main analysis method - orchestrates all detection layers
     */
    public function analyzeRequest(HttpRequest $request): DDoSAssessment
    {
        if (! $this->config->enabled) {
            return DDoSAssessment::createSafe($this->clock);
        }

        return $this->performance->measure('ddos_analysis', function () use ($request) {
            $startTime = $this->clock->time();
            $clientIp = IpAddress::from($this->requestAnalyzer->getClientIp($request));

            // Multi-layer analysis using specialized components
            $analyses = $this->performMultiLayerAnalysis($request, $clientIp->value);

            // Calculate threat level based on all layers
            $threatLevel = $this->threatCalculator->calculateThreatLevel($analyses);

            // Determine attack patterns
            $attackPatterns = $this->patternDetector->identifyAttackPatterns($analyses, $request);

            $endTime = $this->clock->time();
            $processingDuration = $endTime->diff($startTime);

            // Check if processing exceeded threshold
            if ($this->config->isProcessingTimeExceeded($processingDuration)) {
                $this->logger->warning('DDoS analysis exceeded time threshold', [
                    'processing_time' => $processingDuration->toHumanReadable(),
                    'threshold' => $this->config->maxProcessingTime->toHumanReadable(),
                    'client_ip' => $clientIp->value,
                ]);
            }

            // Create comprehensive assessment
            $assessment = new DDoSAssessment(
                threatLevel: $threatLevel,
                attackPatterns: $attackPatterns,
                clientIp: $clientIp,
                analysisResults: $analyses,
                confidence: $this->threatCalculator->calculateConfidence($analyses),
                recommendedAction: $this->threatCalculator->getRecommendedAction($threatLevel),
                processingTime: $processingDuration,
                timestamp: $endTime
            );

            // Log high-confidence threats
            if ($assessment->confidence >= self::HIGH_THRESHOLD) {
                $this->logSecurityThreat($assessment, $request);
            }

            return $assessment;
        });
    }

    /**
     * Execute adaptive response based on threat assessment
     */
    public function executeResponse(DDoSAssessment $assessment, HttpRequest $request): DDoSResponse
    {
        return $this->responseSystem->executeResponse($assessment, $request);
    }

    /**
     * Perform multi-layer analysis using specialized components
     */
    private function performMultiLayerAnalysis(HttpRequest $request, string $clientIp): array
    {
        $analyses = [];

        try {
            // Layer 1: Traffic Pattern Analysis
            $analyses['traffic_patterns'] = $this->trafficAnalyzer->analyzeTrafficPatterns(
                clientIp: $clientIp,
                request: $request,
                rateLimiter: null // Will be resolved internally
            );
        } catch (\Throwable $e) {
            $this->logger->error('Error in traffic pattern analysis', [
                'error' => $e->getMessage(),
                'client_ip' => $clientIp,
            ]);
            $analyses['traffic_patterns'] = ['threat_score' => 0.0, 'confidence' => 0.0];
        }

        try {
            // Layer 2: Geographic Anomaly Detection
            $analyses['geo_anomalies'] = $this->geoDetector->detectAnomalies(
                clientIp: $clientIp,
                geoIpService: null, // Will be resolved internally
                cache: null // Will be resolved internally
            );
        } catch (\Throwable $e) {
            $this->logger->error('Error in geographic anomaly detection', [
                'error' => $e->getMessage(),
                'client_ip' => $clientIp,
            ]);
            $analyses['geo_anomalies'] = ['threat_score' => 0.0, 'confidence' => 0.0];
        }

        try {
            // Layer 3: WAF Pattern Matching
            $analyses['waf_analysis'] = $this->wafAnalyzer->analyzeRequest($request);
        } catch (\Throwable $e) {
            $this->logger->error('Error in WAF analysis', [
                'error' => $e->getMessage(),
                'client_ip' => $clientIp,
            ]);
            $analyses['waf_analysis'] = ['threat_score' => 0.0, 'confidence' => 0.0];
        }

        try {
            // Layer 4: Service Health Monitoring
            $analyses['service_health'] = $this->serviceAnalyzer->analyzeServiceHealth($clientIp);
        } catch (\Throwable $e) {
            $this->logger->error('Error in service health analysis', [
                'error' => $e->getMessage(),
                'client_ip' => $clientIp,
            ]);
            $analyses['service_health'] = ['threat_score' => 0.0, 'confidence' => 0.0];
        }

        try {
            // Layer 5: Request Signature Analysis
            $analyses['request_signature'] = $this->requestAnalyzer->analyzeRequestSignature($request);
        } catch (\Throwable $e) {
            $this->logger->error('Error in request signature analysis', [
                'error' => $e->getMessage(),
                'client_ip' => $clientIp,
            ]);
            $analyses['request_signature'] = ['threat_score' => 0.0, 'confidence' => 0.0];
        }

        return $analyses;
    }

    /**
     * Log high-confidence security threats
     */
    private function logSecurityThreat(DDoSAssessment $assessment, HttpRequest $request): void
    {
        /*$this->securityLogger->logSecurityEvent([
            'event_type' => 'ddos_threat_detected',
            'threat_level' => $assessment->threatLevel->name,
            'confidence' => $assessment->confidence,
            'client_ip' => $assessment->clientIp,
            'attack_patterns' => array_map(fn ($p) => $p->name, $assessment->attackPatterns),
            'request_path' => $request->path,
            'user_agent' => $request->headers->get('User-Agent'),
            'timestamp' => $assessment->timestamp->format('c'),
        ]);*/
    }
}
