<?php

declare(strict_types=1);

use App\Framework\DDoS\Components\ThreatLevelCalculator;
use App\Framework\DDoS\DDoSConfig;
use App\Framework\DDoS\ValueObjects\ThreatLevel;
use App\Framework\Logging\DefaultLogger;
use App\Framework\Logging\Handlers\ConsoleHandler;
use App\Framework\Logging\LogLevel;

beforeEach(function () {
    $this->config = new DDoSConfig(
        criticalThreatThreshold: 0.9,
        highThreatThreshold: 0.7,
        mediumThreatThreshold: 0.3
    );

    // Create a simple logger for testing
    $this->logger = new DefaultLogger(
        minLevel: LogLevel::ERROR,
        handlers: [new ConsoleHandler(LogLevel::ERROR)]
    );

    $this->calculator = new ThreatLevelCalculator($this->logger);
});

describe('ThreatLevelCalculator', function () {

    it('calculates LOW threat for normal scores', function () {
        $analyses = [
            'traffic_patterns' => ['threat_score' => 0.1],
            'geo_anomalies' => ['threat_score' => 0.05],
        ];

        $threatLevel = $this->calculator->calculateThreatLevel($analyses);

        expect($threatLevel)->toBe(ThreatLevel::LOW);
    });

    it('calculates MEDIUM threat for moderate scores', function () {
        $analyses = [
            'traffic_patterns' => ['threat_score' => 0.6],     // 0.3 * 0.6 = 0.18
            'geo_anomalies' => ['threat_score' => 0.7],        // 0.2 * 0.7 = 0.14
            'waf_analysis' => ['threat_score' => 0.4],          // 0.25 * 0.4 = 0.1
        ];
        // Total: 0.18 + 0.14 + 0.1 = 0.42 (above 0.3 threshold)

        $threatLevel = $this->calculator->calculateThreatLevel($analyses);

        expect($threatLevel)->toBe(ThreatLevel::MEDIUM);
    });

    it('calculates HIGH threat for elevated scores', function () {
        $analyses = [
            'traffic_patterns' => ['threat_score' => 1.0],     // 0.3 * 1.0 = 0.3
            'geo_anomalies' => ['threat_score' => 1.0],        // 0.2 * 1.0 = 0.2
            'waf_analysis' => ['threat_score' => 0.8],         // 0.25 * 0.8 = 0.2
            'service_health' => ['threat_score' => 0.0],        // 0.15 * 0.0 = 0.0
        ];
        // Total: 0.3 + 0.2 + 0.2 + 0.0 = 0.7 (exactly HIGH threshold)

        $threatLevel = $this->calculator->calculateThreatLevel($analyses);

        expect($threatLevel)->toBe(ThreatLevel::HIGH);
    });

    it('calculates CRITICAL threat for maximum scores', function () {
        $analyses = [
            'traffic_patterns' => ['threat_score' => 0.95],
            'geo_anomalies' => ['threat_score' => 0.9],
            'waf_analysis' => ['threat_score' => 0.95],
            'service_health' => ['threat_score' => 0.9],
            'request_signature' => ['threat_score' => 0.9],
        ];

        $threatLevel = $this->calculator->calculateThreatLevel($analyses);

        expect($threatLevel)->toBe(ThreatLevel::CRITICAL);
    });

    it('handles edge cases at thresholds', function () {
        // Test MEDIUM threshold (0.3)
        $mediumAnalyses = [
            'traffic_patterns' => ['threat_score' => 1.0], // Will be weighted to exactly 0.3
        ];
        expect($this->calculator->calculateThreatLevel($mediumAnalyses))->toBe(ThreatLevel::MEDIUM);

        // Test HIGH threshold (0.7)
        $highAnalyses = [
            'traffic_patterns' => ['threat_score' => 1.0], // 0.3 weight
            'geo_anomalies' => ['threat_score' => 1.0],     // 0.2 weight
            'waf_analysis' => ['threat_score' => 0.8],       // 0.25 weight * 0.8 = 0.2
        ];
        // Total: 0.3 + 0.2 + 0.2 = 0.7
        expect($this->calculator->calculateThreatLevel($highAnalyses))->toBe(ThreatLevel::HIGH);
    });

    it('handles empty analysis results', function () {
        $threatLevel = $this->calculator->calculateThreatLevel([]);

        expect($threatLevel)->toBe(ThreatLevel::LOW);
    });

    it('calculates confidence from multiple analyses', function () {
        $analyses = [
            'traffic_patterns' => ['threat_score' => 0.6, 'confidence' => 0.8],
            'geo_anomalies' => ['threat_score' => 0.4, 'confidence' => 0.9],
            'waf_analysis' => ['threat_score' => 0.7, 'confidence' => 0.7],
        ];

        $confidence = $this->calculator->calculateConfidence($analyses);

        expect($confidence)->toBeBetween(0.0, 1.0);
        expect($confidence)->toBeGreaterThan(0.7); // Average should be around 0.8
    });

    it('handles missing confidence values', function () {
        $analyses = [
            'traffic_patterns' => ['threat_score' => 0.6], // No confidence
            'geo_anomalies' => ['threat_score' => 0.4, 'confidence' => 0.8],
        ];

        $confidence = $this->calculator->calculateConfidence($analyses);

        expect($confidence)->toBe(0.8); // Only one confidence value available
    });

});

describe('Threat Level Recommendations', function () {

    it('provides appropriate action recommendations', function () {
        expect($this->calculator->getRecommendedAction(ThreatLevel::LOW))->toBe('ALLOW');
        expect($this->calculator->getRecommendedAction(ThreatLevel::MEDIUM))->toBe('RATE_LIMIT');
        expect($this->calculator->getRecommendedAction(ThreatLevel::HIGH))->toBe('ENHANCED_MONITORING');
        expect($this->calculator->getRecommendedAction(ThreatLevel::CRITICAL))->toBe('BLOCK_IMMEDIATELY');
    });

    it('suggests rate limiting for medium threats', function () {
        $recommendation = $this->calculator->getRecommendedAction(ThreatLevel::MEDIUM);

        expect($recommendation)->toBe('RATE_LIMIT');
    });

    it('suggests enhanced monitoring for high threats', function () {
        $recommendation = $this->calculator->getRecommendedAction(ThreatLevel::HIGH);

        expect($recommendation)->toBe('ENHANCED_MONITORING');
    });

    it('suggests immediate blocking for critical threats', function () {
        $recommendation = $this->calculator->getRecommendedAction(ThreatLevel::CRITICAL);

        expect($recommendation)->toBe('BLOCK_IMMEDIATELY');
    });

});
