<?php

declare(strict_types=1);

use App\Framework\DDoS\Components\AttackPatternDetector;
use App\Framework\DDoS\DDoSConfig;
use App\Framework\DDoS\ValueObjects\AttackPattern;
use App\Framework\Logging\DefaultLogger;
use App\Framework\Logging\LogLevel;

require_once __DIR__ . '/../Helpers/TestHelpers.php';

beforeEach(function () {
    // Create development config (more permissive for testing)
    $config = DDoSConfig::development();

    // Create logger
    $logger = new DefaultLogger(LogLevel::DEBUG);

    $this->detector = new AttackPatternDetector($config, $logger);
});

describe('AttackPatternDetector', function () {

    it('detects volumetric attacks', function () {
        $analysisResults = [
            'traffic_patterns' => [
                'threat_score' => 0.9, // Higher than development config threshold (0.8)
                'requests_per_minute' => 500,
                'normal_rate' => 50,
            ],
        ];

        $request = createTestRequest('192.168.1.100', 'GET', '/api/data');

        $patterns = $this->detector->identifyAttackPatterns($analysisResults, $request);

        expect($patterns)->toContain(AttackPattern::VOLUMETRIC);
    });

    it('detects distributed attacks', function () {
        $analysisResults = [
            'geo_anomalies' => [
                'threat_score' => 0.7,
                'unique_countries' => 15,
                'geographic_diversity' => 0.9,
            ],
        ];

        $request = createTestRequest('10.0.0.1', 'POST', '/api/login');

        $patterns = $this->detector->identifyAttackPatterns($analysisResults, $request);

        expect($patterns)->toContain(AttackPattern::DISTRIBUTED);
    });

    it('detects bot attacks from user agent patterns', function () {
        $analysisResults = [
            'request_signature' => [
                'threat_score' => 0.6,
                'user_agent_suspicion' => 0.8,
                'automation_indicators' => ['unusual_timing', 'fixed_intervals'],
            ],
        ];

        $request = createTestRequest('192.168.1.200', 'GET', '/scrape-data', [
            'User-Agent' => 'ScrapingBot/2.0 (automated)',
        ]);

        $patterns = $this->detector->identifyAttackPatterns($analysisResults, $request);

        expect($patterns)->toContain(AttackPattern::BOTNET);
    });

    it('detects application layer attacks', function () {
        $analysisResults = [
            'waf_analysis' => [
                'threat_score' => 0.9,
                'malicious_patterns' => ['sql_injection', 'xss_attempt'],
                'payload_analysis' => 'high_risk',
            ],
        ];

        $request = createTestRequest('192.168.1.300', 'POST', '/api/search', [], [
            'query' => "'; DROP TABLE users; --",
        ]);

        $patterns = $this->detector->identifyAttackPatterns($analysisResults, $request);

        expect($patterns)->toContain(AttackPattern::APPLICATION_LAYER);
    });

    it('detects slow rate attacks', function () {
        $analysisResults = [
            'traffic_patterns' => [
                'threat_score' => 0.4,
                'requests_per_minute' => 30,
                'sustained_duration' => 3600, // 1 hour
                'pattern_consistency' => 0.95,
            ],
        ];

        $request = createTestRequest('192.168.1.400', 'GET', '/expensive-operation');

        $patterns = $this->detector->identifyAttackPatterns($analysisResults, $request);

        expect($patterns)->toContain(AttackPattern::SLOWLORIS);
    });

    it('detects mixed attack patterns', function () {
        $analysisResults = [
            'traffic_patterns' => [
                'threat_score' => 0.8,
                'requests_per_minute' => 300,
            ],
            'geo_anomalies' => [
                'threat_score' => 0.6,
                'unique_countries' => 10,
            ],
            'waf_analysis' => [
                'threat_score' => 0.7,
                'malicious_patterns' => ['xss_attempt'],
            ],
        ];

        $request = createTestRequest('192.168.1.500', 'POST', '/api/submit');

        $patterns = $this->detector->identifyAttackPatterns($analysisResults, $request);

        expect($patterns)->toHaveCount(3);
        expect($patterns)->toContain(AttackPattern::VOLUMETRIC);
        expect($patterns)->toContain(AttackPattern::DISTRIBUTED);
        expect($patterns)->toContain(AttackPattern::APPLICATION_LAYER);
    });

    it('returns empty array for normal traffic', function () {
        $analysisResults = [
            'traffic_patterns' => [
                'threat_score' => 0.1,
                'requests_per_minute' => 15,
            ],
            'geo_anomalies' => [
                'threat_score' => 0.05,
                'unique_countries' => 1,
            ],
        ];

        $request = createTestRequest('192.168.1.600', 'GET', '/api/health');

        $patterns = $this->detector->identifyAttackPatterns($analysisResults, $request);

        expect($patterns)->toBeEmpty();
    });

    it('identifies coordinated attack patterns', function () {
        $analysisResults = [
            'traffic_patterns' => [
                'threat_score' => 0.6,
                'coordination_score' => 0.8,
                'timing_patterns' => 'synchronized',
            ],
        ];

        $request = createTestRequest('192.168.1.700', 'GET', '/target-endpoint');

        $patterns = $this->detector->identifyAttackPatterns($analysisResults, $request);

        expect($patterns)->toContain(AttackPattern::DISTRIBUTED);
    });

    it('detects amplification attacks', function () {
        $analysisResults = [
            'traffic_patterns' => [
                'threat_score' => 0.7,
                'amplification_ratio' => 50,
                'response_size_anomaly' => 0.9,
            ],
        ];

        $request = createTestRequest('192.168.1.800', 'GET', '/api/export-large-dataset');

        $patterns = $this->detector->identifyAttackPatterns($analysisResults, $request);

        expect($patterns)->toContain(AttackPattern::AMPLIFICATION);
    });

    it('handles malformed analysis results', function () {
        $analysisResults = [
            'invalid_layer' => null,
            'broken_data' => 'not_an_array',
        ];

        $request = createTestRequest('192.168.1.900', 'GET', '/api/test');

        $patterns = $this->detector->identifyAttackPatterns($analysisResults, $request);

        expect($patterns)->toBeArray();
    });

    it('calculates pattern confidence scores', function () {
        $analysisResults = [
            'traffic_patterns' => [
                'threat_score' => 0.8,
                'confidence' => 0.9,
            ],
        ];

        $request = createTestRequest('192.168.1.100', 'GET', '/api/data');

        $confidence = $this->detector->calculatePatternConfidence($analysisResults);

        expect($confidence)->toBeBetween(0.0, 1.0);
        expect($confidence)->toBeGreaterThan(0.7);
    });

    it('provides pattern severity assessment', function () {
        $patterns = [
            AttackPattern::VOLUMETRIC,
            AttackPattern::APPLICATION_LAYER,
        ];

        $severity = $this->detector->assessPatternSeverity($patterns);

        expect($severity)->toBeIn(['low', 'medium', 'high', 'critical']);
    });

});

describe('Pattern Analysis Details', function () {

    it('provides detailed pattern analysis', function () {
        $analysisResults = [
            'traffic_patterns' => [
                'threat_score' => 0.8,
                'requests_per_minute' => 500,
                'peak_detection' => true,
            ],
        ];

        $request = createTestRequest('192.168.1.100', 'GET', '/api/data');

        $details = $this->detector->getPatternAnalysisDetails($analysisResults, $request);

        expect($details)->toHaveKeys([
            'detected_patterns',
            'confidence_scores',
            'risk_factors',
            'recommendations',
        ]);
    });

    it('tracks pattern evolution over time', function () {
        $historicalData = [
            ['timestamp' => time() - 3600, 'patterns' => [AttackPattern::VOLUMETRIC]],
            ['timestamp' => time() - 1800, 'patterns' => [AttackPattern::VOLUMETRIC, AttackPattern::BOTNET]],
            ['timestamp' => time(), 'patterns' => [AttackPattern::DISTRIBUTED]],
        ];

        $evolution = $this->detector->analyzePatternEvolution($historicalData);

        expect($evolution)->toHaveKeys(['trend', 'escalation_detected', 'pattern_changes']);
        expect($evolution['escalation_detected'])->toBeTrue();
    });

    it('generates pattern fingerprints', function () {
        $analysisResults = [
            'traffic_patterns' => ['threat_score' => 0.8],
            'geo_anomalies' => ['threat_score' => 0.6],
        ];

        $request = createTestRequest('192.168.1.100', 'GET', '/api/data');

        $fingerprint = $this->detector->generatePatternFingerprint($analysisResults, $request);

        expect($fingerprint)->toBeString();
        expect(strlen($fingerprint))->toBeGreaterThan(10);
    });

});

// Helper functions are now in ../Helpers/TestHelpers.php
