<?php

declare(strict_types=1);

namespace App\Framework\DDoS\Components;

use App\Framework\DDoS\ValueObjects\ThreatLevel;
use App\Framework\Logging\Logger;

/**
 * Calculates threat levels based on multi-layer analysis results
 */
final class ThreatLevelCalculator
{
    private const float CRITICAL_THRESHOLD = 0.9;
    private const float HIGH_THRESHOLD = 0.7;
    private const float MEDIUM_THRESHOLD = 0.3;

    /**
     * Default weights for different analysis layers
     */
    private array $defaultWeights = [
        'traffic_patterns' => 0.3,
        'geo_anomalies' => 0.2,
        'waf_analysis' => 0.25,
        'service_health' => 0.15,
        'request_signature' => 0.1,
    ];

    public function __construct(
        private readonly Logger $logger,
        private readonly array $weights = []
    ) {
    }

    /**
     * Calculate overall threat level from all analysis layers
     *
     * @param array $analyses Multi-layer analysis results
     * @return ThreatLevel The calculated threat level
     */
    public function calculateThreatLevel(array $analyses): ThreatLevel
    {
        $totalScore = 0.0;
        $weights = $this->weights ?: $this->defaultWeights;

        foreach ($analyses as $layerName => $result) {
            $layerScore = $this->extractThreatScore($result);
            $weight = $weights[$layerName] ?? 0.0;
            $totalScore += $layerScore * $weight;
        }

        $this->logger->debug('Calculated threat level', [
            'total_score' => $totalScore,
            'analyses_count' => count($analyses),
        ]);

        return match (true) {
            $totalScore >= self::CRITICAL_THRESHOLD => ThreatLevel::CRITICAL,
            $totalScore >= self::HIGH_THRESHOLD => ThreatLevel::HIGH,
            $totalScore >= self::MEDIUM_THRESHOLD => ThreatLevel::MEDIUM,
            default => ThreatLevel::LOW
        };
    }

    /**
     * Calculate confidence level from analysis results
     *
     * @param array $analyses Multi-layer analysis results
     * @return float Confidence level (0.0-1.0)
     */
    public function calculateConfidence(array $analyses): float
    {
        $confidenceSum = 0.0;
        $count = 0;

        foreach ($analyses as $result) {
            if (is_array($result) && isset($result['confidence'])) {
                $confidenceSum += $result['confidence'];
                $count++;
            }
        }

        return $count > 0 ? $confidenceSum / $count : 0.0;
    }

    /**
     * Extract threat score from different analysis result types
     *
     * @param mixed $analysisResult Analysis result from various components
     * @return float Normalized threat score (0.0-1.0)
     */
    private function extractThreatScore($analysisResult): float
    {
        // Extract threat score from different analysis result types
        if (is_array($analysisResult)) {
            return $analysisResult['threat_score'] ?? 0.0;
        }

        // Handle WAF decision results
        if (method_exists($analysisResult, 'getThreatAssessment')) {
            return $analysisResult->getThreatAssessment()->getThreatLevel()->value / 100.0;
        }

        return 0.0;
    }

    /**
     * Get recommended action based on threat level
     *
     * @param ThreatLevel $threatLevel The calculated threat level
     * @return string Recommended action code
     */
    public function getRecommendedAction(ThreatLevel $threatLevel): string
    {
        return match ($threatLevel) {
            ThreatLevel::CRITICAL => 'BLOCK_IMMEDIATELY',
            ThreatLevel::HIGH => 'ENHANCED_MONITORING',
            ThreatLevel::MEDIUM => 'RATE_LIMIT',
            ThreatLevel::LOW => 'ALLOW'
        };
    }
}
