﻿<?php

declare(strict_types=1);

/**
 * NoSQL Injection Detection Tester v1.0
 * Specialized testing module for NoSQL injection patterns
 */

final class NoSQLInjectionTester {
    private const TEST_KEY_HEADER = 'X-Security-Test';
    private string $testKey;
    private array $testResults = [];
    private float $startTime;
    private array $performanceMetrics = [];

    public function __construct() {
        $this->startTime = microtime(true);
        $this->initializeTestEnvironment();
    }

    private function initializeTestEnvironment(): void {
        $testKeyFile = __DIR__ . '/.test_key';
        
        if (!file_exists($testKeyFile)) {
            $this->testKey = $this->generateSecureTestKey();
            file_put_contents($testKeyFile, $this->testKey, LOCK_EX);
            chmod($testKeyFile, 0600);
            echo "Generated new test key: " . substr($this->testKey, 0, 16) . "...\n";
        } else {
            $this->testKey = trim(file_get_contents($testKeyFile));
        }

        $_SERVER['HTTP_X_SECURITY_TEST'] = $this->testKey;
    }

    private function generateSecureTestKey(): string {
        return bin2hex(random_bytes(32));
    }

    /**
     * Run comprehensive NoSQL injection test suite
     */
    public function runAllNoSQLTests(): array {
        echo "Starting NoSQL Injection Detection Tests...\n";
        echo "Test Key: " . substr($this->testKey, 0, 16) . "...\n\n";

        $this->testNoSQLPatternValidation();
        $this->testMongoDBOperators();
        $this->testAuthenticationBypass();
        $this->testCodeExecution();
        $this->testDatabaseSpecific();
        $this->testFalsePositives();
        $this->testPerformance();
        $this->testSecurity();

        return $this->generateNoSQLTestReport();
    }

    /**
     * Test NoSQL pattern validation and regex integrity
     */
    private function testNoSQLPatternValidation(): void {
        echo "1. Testing NoSQL Pattern Validation...\n";

        $patternDetails = HackDetectionService::getPatternDetails();
        $nosqlPatterns = $patternDetails['nosqlinjection'] ?? [];

        $this->testResults['pattern_validation'] = [
            'total_patterns' => $nosqlPatterns['total_patterns'] ?? 0,
            'test_cases_count' => count($nosqlPatterns['test_cases'] ?? []),
            'score_range' => $nosqlPatterns['score_range'] ?? [],
            'test_results' => [],
            'passed_tests' => 0,
            'failed_tests' => 0
        ];

        if (!empty($nosqlPatterns['test_cases'])) {
            foreach ($nosqlPatterns['test_cases'] as $testCase) {
                $testResult = $this->runNoSQLTestCase($testCase);
                $this->testResults['pattern_validation']['test_results'][] = $testResult;

                if ($testResult['passed']) {
                    $this->testResults['pattern_validation']['passed_tests']++;
                } else {
                    $this->testResults['pattern_validation']['failed_tests']++;
                }
            }
        }

        echo "   ✓ Tested " . count($nosqlPatterns['test_cases'] ?? []) . " NoSQL pattern test cases\n";
    }

    /**
     * Run individual NoSQL test case
     */
    private function runNoSQLTestCase(array $testCase): array {
        $this->setupTestEnvironment($testCase['input'] ?? []);
        
        $startTime = microtime(true);
        $result = HackDetectionService::detectHackAttempt();
        $endTime = microtime(true);

        $executionTime = $endTime - $startTime;
        $this->performanceMetrics[] = $executionTime;

        $expectedScore = $testCase['expected_score'] ?? 0;
        $actualScore = $result['confidence_score'];
        $passed = $this->evaluateNoSQLTestResult($testCase, $result);

        return [
            'description' => $testCase['description'] ?? 'Unknown test',
            'expected_score' => $expectedScore,
            'actual_score' => $actualScore,
            'execution_time' => $executionTime,
            'passed' => $passed,
            'detected_vectors' => $result['detected_vectors'],
            'risk_level' => $result['risk_level'],
            'is_hack' => $result['is_hack'],
            'test_mode' => $result['test_mode'] ?? false
        ];
    }

    /**
     * Evaluate NoSQL test result
     */
    private function evaluateNoSQLTestResult(array $testCase, array $result): bool {
        $expectedScore = $testCase['expected_score'] ?? 0;
        $expectedDetection = $testCase['should_detect'] ?? ($expectedScore > 0);
        
        $actualScore = $result['confidence_score'];
        $actualDetection = $result['is_hack'];

        // Allow tolerance for score matching
        $scoreTolerance = 15; // Slightly higher tolerance for NoSQL patterns
        $scoreMatch = abs($expectedScore - $actualScore) <= $scoreTolerance;
        
        $detectionMatch = $expectedDetection === $actualDetection;

        return $scoreMatch && $detectionMatch;
    }

    /**
     * Test MongoDB operator injection
     */
    private function testMongoDBOperators(): void {
        echo "2. Testing MongoDB Operator Injection...\n";

        $operatorTests = [
            [
                'description' => 'MongoDB comparison operators',
                'tests' => [
                    ['input' => '{"username": "admin", "password": {"$ne": ""}}', 'expected_score' => 80],
                    ['input' => '{"age": {"$gt": 18}}', 'expected_score' => 80],
                    ['input' => '{"score": {"$gte": 100}}', 'expected_score' => 80],
                    ['input' => '{"price": {"$lt": 50}}', 'expected_score' => 80],
                    ['input' => '{"quantity": {"$lte": 10}}', 'expected_score' => 80],
                ]
            ],
            [
                'description' => 'MongoDB logical operators',
                'tests' => [
                    ['input' => '{"$or": [{"role": "admin"}, {"isAdmin": true}]}', 'expected_score' => 88],
                    ['input' => '{"$and": [{"status": "active"}, {"verified": true}]}', 'expected_score' => 85],
                    ['input' => '{"$nor": [{"role": "user"}, {"status": "inactive"}]}', 'expected_score' => 86],
                    ['input' => '{"role": {"$not": {"$eq": "user"}}}', 'expected_score' => 82],
                ]
            ],
            [
                'description' => 'MongoDB array operators',
                'tests' => [
                    ['input' => '{"tags": {"$in": ["admin", "superuser"]}}', 'expected_score' => 83],
                    ['input' => '{"categories": {"$nin": ["public", "guest"]}}', 'expected_score' => 83],
                    ['input' => '{"permissions": {"$all": ["read", "write", "execute"]}}', 'expected_score' => 82],
                    ['input' => '{"items": {"$size": 5}}', 'expected_score' => 80],
                ]
            ],
            [
                'description' => 'MongoDB element operators',
                'tests' => [
                    ['input' => '{"email": {"$exists": true}}', 'expected_score' => 81],
                    ['input' => '{"phone": {"$type": "string"}}', 'expected_score' => 80],
                    ['input' => '{"age": {"$mod": [2, 0]}}', 'expected_score' => 82],
                    ['input' => '{"scores": {"$elemMatch": {"$gte": 80, "$lt": 90}}}', 'expected_score' => 85],
                ]
            ]
        ];

        $this->testResults['mongodb_operators'] = [
            'categories_tested' => count($operatorTests),
            'total_tests' => 0,
            'passed_tests' => 0,
            'category_results' => []
        ];

        foreach ($operatorTests as $category) {
            $categoryResults = [
                'category' => $category['description'],
                'tests' => [],
                'passed' => 0,
                'failed' => 0
            ];

            foreach ($category['tests'] as $test) {
                $this->setupTestEnvironment([
                    'post' => ['query' => $test['input']],
                    'server' => [
                        'REQUEST_URI' => '/api/query',
                        'HTTP_CONTENT_TYPE' => 'application/json',
                        'HTTP_USER_AGENT' => 'NoSQL-Tester/1.0'
                    ]
                ]);

                $result = HackDetectionService::detectHackAttempt();
                $passed = $result['confidence_score'] >= $test['expected_score'];

                $testResult = [
                    'input' => $test['input'],
                    'expected_score' => $test['expected_score'],
                    'actual_score' => $result['confidence_score'],
                    'passed' => $passed,
                    'detected' => $result['is_hack'],
                    'vectors' => $result['detected_vectors']
                ];

                $categoryResults['tests'][] = $testResult;

                if ($passed) {
                    $categoryResults['passed']++;
                    $this->testResults['mongodb_operators']['passed_tests']++;
                } else {
                    $categoryResults['failed']++;
                }

                $this->testResults['mongodb_operators']['total_tests']++;
            }

            $this->testResults['mongodb_operators']['category_results'][] = $categoryResults;
        }

        echo "   ✓ Tested " . $this->testResults['mongodb_operators']['total_tests'] . " MongoDB operator patterns\n";
    }

    /**
     * Test authentication bypass techniques
     */
    private function testAuthenticationBypass(): void {
        echo "3. Testing Authentication Bypass Techniques...\n";

        $authBypassTests = [
            [
                'description' => 'Classic authentication bypass',
                'input' => '{"$or": [{"username": "admin"}, {"password": {"$ne": "invalid"}}]}',
                'expected_score' => 88,
                'context' => 'login'
            ],
            [
                'description' => 'Boolean-based bypass',
                'input' => '{"$where": "this.username == \'admin\' && this.password != \'\'"}',
                'expected_score' => 95,
                'context' => 'login'
            ],
            [
                'description' => 'Regex-based user enumeration',
                'input' => '{"username": {"$regex": "admin.*"}, "password": {"$exists": true}}',
                'expected_score' => 85,
                'context' => 'login'
            ],
            [
                'description' => 'Type confusion attack',
                'input' => '{"username": "admin", "password": {"$ne": null}}',
                'expected_score' => 80,
                'context' => 'login'
            ],
            [
                'description' => 'Array-based bypass',
                'input' => '{"username": "admin", "password": {"$in": ["pass1", "pass2", "pass3"]}}',
                'expected_score' => 83,
                'context' => 'login'
            ]
        ];

        $this->testResults['authentication_bypass'] = [
            'total_tests' => count($authBypassTests),
            'passed_tests' => 0,
            'failed_tests' => 0,
            'test_results' => []
        ];

        foreach ($authBypassTests as $test) {
            $this->setupTestEnvironment([
                'post' => ['credentials' => $test['input']],
                'server' => [
                    'REQUEST_URI' => '/api/' . $test['context'],
                    'HTTP_CONTENT_TYPE' => 'application/json',
                    'HTTP_USER_AGENT' => 'Auth-Tester/1.0'
                ]
            ]);

            $result = HackDetectionService::detectHackAttempt();
            $passed = $result['confidence_score'] >= $test['expected_score'];

            $testResult = [
                'description' => $test['description'],
                'input' => $test['input'],
                'expected_score' => $test['expected_score'],
                'actual_score' => $result['confidence_score'],
                'passed' => $passed,
                'detected_vectors' => $result['detected_vectors']
            ];

            $this->testResults['authentication_bypass']['test_results'][] = $testResult;

            if ($passed) {
                $this->testResults['authentication_bypass']['passed_tests']++;
            } else {
                $this->testResults['authentication_bypass']['failed_tests']++;
            }
        }

        echo "   ✓ Tested " . count($authBypassTests) . " authentication bypass techniques\n";
    }

    /**
     * Test code execution vectors
     */
    private function testCodeExecution(): void {
        echo "4. Testing Code Execution Vectors...\n";

        $codeExecutionTests = [
            [
                'description' => 'MongoDB $function operator',
                'input' => '{"$function": {"body": "function() { return process.env.SECRET_KEY; }"}}',
                'expected_score' => 98,
                'severity' => 'critical'
            ],
            [
                'description' => 'MongoDB $eval operator',
                'input' => '{"$eval": "function() { db.users.drop(); return true; }"}',
                'expected_score' => 99,
                'severity' => 'critical'
            ],
            [
                'description' => 'MongoDB $where with system commands',
                'input' => '{"$where": "function() { return this.constructor.constructor(\'return process\')().mainModule.require(\'child_process\').execSync(\'id\').toString() }"}',
                'expected_score' => 95,
                'severity' => 'critical'
            ],
            [
                'description' => 'JavaScript code in aggregation',
                'input' => '{"pipeline": [{"$project": {"result": {"$function": {"body": "function() { return \'malicious\'; }"}}}}]}',
                'expected_score' => 98,
                'severity' => 'critical'
            ]
        ];

        $this->testResults['code_execution'] = [
            'total_tests' => count($codeExecutionTests),
            'passed_tests' => 0,
            'failed_tests' => 0,
            'critical_tests' => 0,
            'test_results' => []
        ];

        foreach ($codeExecutionTests as $test) {
            $this->setupTestEnvironment([
                'post' => ['aggregation' => $test['input']],
                'server' => [
                    'REQUEST_URI' => '/api/aggregate',
                    'HTTP_CONTENT_TYPE' => 'application/json',
                    'HTTP_USER_AGENT' => 'Aggregation-Tester/1.0'
                ]
            ]);

            $result = HackDetectionService::detectHackAttempt();
            $passed = $result['confidence_score'] >= $test['expected_score'];

            $testResult = [
                'description' => $test['description'],
                'input' => $test['input'],
                'expected_score' => $test['expected_score'],
                'actual_score' => $result['confidence_score'],
                'severity' => $test['severity'],
                'passed' => $passed,
                'risk_level' => $result['risk_level']
            ];

            $this->testResults['code_execution']['test_results'][] = $testResult;

            if ($passed) {
                $this->testResults['code_execution']['passed_tests']++;
                if ($test['severity'] === 'critical') {
                    $this->testResults['code_execution']['critical_tests']++;
                }
            } else {
                $this->testResults['code_execution']['failed_tests']++;
            }
        }

        echo "   ✓ Tested " . count($codeExecutionTests) . " code execution vectors\n";
    }

    /**
     * Test database-specific NoSQL injection
     */
    private function testDatabaseSpecific(): void {
        echo "5. Testing Database-Specific NoSQL Injection...\n";

        $databaseTests = [
            'couchdb' => [
                [
                    'description' => 'CouchDB selector injection',
                    'input' => '{"selector": {"$or": [{"role": "admin"}, {"_id": {"$gt": null}}]}}',
                    'expected_score' => 72
                ],
                [
                    'description' => 'CouchDB complex selector',
                    'input' => '{"selector": {"username": "admin", "password": {"$ne": "wrong"}}}',
                    'expected_score' => 70
                ]
            ],
            'redis' => [
                [
                    'description' => 'Redis EVAL command injection',
                    'input' => 'eval "return redis.call(\'keys\', \'*\')" 0',
                    'expected_score' => 85
                ],
                [
                    'description' => 'Redis EVALSHA injection',
                    'input' => 'evalsha "abc123" 1 "user:*"',
                    'expected_score' => 85
                ]
            ],
            'cassandra' => [
                [
                    'description' => 'CQL injection with ALLOW FILTERING',
                    'input' => 'SELECT * FROM users WHERE username = \'admin\' ALLOW FILTERING',
                    'expected_score' => 70
                ]
            ],
            'graphql' => [
                [
                    'description' => 'GraphQL filter injection',
                    'input' => 'query { users(filter: {OR: [{username: "admin"}, {password: {ne: ""}}]}) { id } }',
                    'expected_score' => 68
                ],
                [
                    'description' => 'GraphQL where clause injection',
                    'input' => 'query { products(where: {price: {gt: 0, lt: 100}}) { name } }',
                    'expected_score' => 67
                ]
            ]
        ];

        $this->testResults['database_specific'] = [
            'databases_tested' => count($databaseTests),
            'total_tests' => 0,
            'passed_tests' => 0,
            'database_results' => []
        ];

        foreach ($databaseTests as $dbType => $tests) {
            $dbResults = [
                'database' => $dbType,
                'tests' => [],
                'passed' => 0,
                'failed' => 0
            ];

            foreach ($tests as $test) {
                $this->setupTestEnvironment([
                    'post' => ['query' => $test['input']],
                    'server' => [
                        'REQUEST_URI' => '/api/' . $dbType,
                        'HTTP_CONTENT_TYPE' => 'application/json',
                        'HTTP_USER_AGENT' => $dbType . '-Client/1.0'
                    ]
                ]);

                $result = HackDetectionService::detectHackAttempt();
                $passed = $result['confidence_score'] >= $test['expected_score'];

                $testResult = [
                    'description' => $test['description'],
                    'input' => $test['input'],
                    'expected_score' => $test['expected_score'],
                    'actual_score' => $result['confidence_score'],
                    'passed' => $passed
                ];

                $dbResults['tests'][] = $testResult;

                if ($passed) {
                    $dbResults['passed']++;
                    $this->testResults['database_specific']['passed_tests']++;
                } else {
                    $dbResults['failed']++;
                }

                $this->testResults['database_specific']['total_tests']++;
            }

            $this->testResults['database_specific']['database_results'][] = $dbResults;
        }

        echo "   ✓ Tested " . $this->testResults['database_specific']['total_tests'] . " database-specific patterns\n";
    }

    /**
     * Test false positive prevention
     */
    private function testFalsePositives(): void {
        echo "6. Testing False Positive Prevention...\n";

        $legitimateQueries = [
            [
                'description' => 'Legitimate user query',
                'input' => [
                    'post' => ['filter' => '{"username": "john_doe", "status": "active"}'],
                    'server' => [
                        'REQUEST_URI' => '/api/users',
                        'HTTP_CONTENT_TYPE' => 'application/json',
                        'HTTP_USER_AGENT' => 'MongoDB-Client/1.0'
                    ]
                ],
                'should_detect' => false
            ],
            [
                'description' => 'Simple product search',
                'input' => [
                    'post' => ['search' => '{"category": "electronics", "price": {"$lt": 1000}}'],
                    'server' => [
                        'REQUEST_URI' => '/api/products',
                        'HTTP_CONTENT_TYPE' => 'application/json',
                        'HTTP_USER_AGENT' => 'Product-Service/1.0'
                    ]
                ],
                'should_detect' => false
            ],
            [
                'description' => 'Array query for categories',
                'input' => [
                    'post' => ['categories' => '{"$in": ["books", "music", "movies"]}'],
                    'server' => [
                        'REQUEST_URI' => '/api/items',
                        'HTTP_CONTENT_TYPE' => 'application/json',
                        'HTTP_USER_AGENT' => 'Catalog-Service/1.0'
                    ]
                ],
                'should_detect' => false
            ],
            [
                'description' => 'Date range query',
                'input' => [
                    'post' => ['range' => '{"created": {"$gte": "2023-01-01", "$lte": "2023-12-31"}}'],
                    'server' => [
                        'REQUEST_URI' => '/api/analytics',
                        'HTTP_CONTENT_TYPE' => 'application/json',
                        'HTTP_USER_AGENT' => 'Analytics-Service/1.0'
                    ]
                ],
                'should_detect' => false
            ],
            [
                'description' => 'Pagination query',
                'input' => [
                    'post' => ['pagination' => '{"skip": 0, "limit": 10, "sort": {"created": -1}}'],
                    'server' => [
                        'REQUEST_URI' => '/api/posts',
                        'HTTP_CONTENT_TYPE' => 'application/json',
                        'HTTP_USER_AGENT' => 'Blog-Service/1.0'
                    ]
                ],
                'should_detect' => false
            ]
        ];

        $this->testResults['false_positives'] = [
            'total_tests' => count($legitimateQueries),
            'passed_tests' => 0,
            'failed_tests' => 0,
            'test_results' => []
        ];

        foreach ($legitimateQueries as $test) {
            $this->setupTestEnvironment($test['input']);
            
            $result = HackDetectionService::detectHackAttempt();
            $passed = $result['is_hack'] === $test['should_detect'];

            $testResult = [
                'description' => $test['description'],
                'expected_detection' => $test['should_detect'],
                'actual_detection' => $result['is_hack'],
                'confidence_score' => $result['confidence_score'],
                'passed' => $passed
            ];

            $this->testResults['false_positives']['test_results'][] = $testResult;

            if ($passed) {
                $this->testResults['false_positives']['passed_tests']++;
            } else {
                $this->testResults['false_positives']['failed_tests']++;
            }
        }

        echo "   ✓ Tested " . count($legitimateQueries) . " legitimate NoSQL queries\n";
    }

    /**
     * Test performance metrics
     */
    private function testPerformance(): void {
        echo "7. Testing Performance...\n";

        $performanceTests = [];
        $totalTime = 0;
        $testCount = 20; // More iterations for performance testing

        $testQueries = [
            '{"username": "admin", "password": {"$ne": ""}}',
            '{"$or": [{"role": "admin"}, {"isAdmin": true}]}',
            '{"$where": "function() { return true; }"}',
            '{"category": {"$in": ["A", "B", "C"]}}',
            '{"status": "active", "verified": true}'
        ];

        for ($i = 0; $i < $testCount; $i++) {
            $query = $testQueries[$i % count($testQueries)];
            
            $this->setupTestEnvironment([
                'post' => ['query' => $query],
                'server' => [
                    'REQUEST_URI' => '/api/performance',
                    'HTTP_CONTENT_TYPE' => 'application/json'
                ]
            ]);

            $startTime = microtime(true);
            $result = HackDetectionService::detectHackAttempt();
            $endTime = microtime(true);

            $executionTime = $endTime - $startTime;
            $totalTime += $executionTime;

            $performanceTests[] = [
                'iteration' => $i + 1,
                'query_type' => $this->getQueryType($query),
                'execution_time' => $executionTime,
                'memory_usage' => memory_get_peak_usage(true),
                'detected' => $result['is_hack'],
                'score' => $result['confidence_score']
            ];
        }

        $this->testResults['performance_tests'] = [
            'iterations' => $testCount,
            'average_time' => $totalTime / $testCount,
            'total_time' => $totalTime,
            'queries_per_second' => $testCount / $totalTime,
            'memory_usage' => memory_get_peak_usage(true),
            'tests' => $performanceTests
        ];

        echo "   ✓ Completed " . $testCount . " performance iterations\n";
    }

    /**
     * Get query type for categorization
     */
    private function getQueryType(string $query): string {
        if (strpos($query, '$where') !== false) return 'javascript_execution';
        if (strpos($query, '$or') !== false) return 'logical_operator';
        if (strpos($query, '$in') !== false) return 'array_operator';
        if (strpos($query, '$ne') !== false) return 'comparison_operator';
        return 'simple_query';
    }

    /**
     * Test security measures
     */
    private function testSecurity(): void {
        echo "8. Testing Security Measures...\n";

        $securityTests = [];

        // Test 1: Verify test mode requires valid key
        $originalKey = $_SERVER['HTTP_X_SECURITY_TEST'];
        $_SERVER['HTTP_X_SECURITY_TEST'] = 'invalid-key';
        $resultWithoutKey = HackDetectionService::detectHackAttempt();
        $_SERVER['HTTP_X_SECURITY_TEST'] = $originalKey;

        $securityTests[] = [
            'test' => 'Test mode requires valid key',
            'passed' => !$resultWithoutKey['test_mode'],
            'description' => 'System should not be in test mode with invalid key'
        ];

        // Test 2: Verify no logging in test mode
        $this->setupTestEnvironment([
            'post' => ['query' => '{"$where": "function() { return true; }"}'],
            'server' => ['REQUEST_URI' => '/api/test']
        ]);

        $logFile = __DIR__ . '/../logs/security.log';
        $originalLogSize = file_exists($logFile) ? filesize($logFile) : 0;
        
        $result = HackDetectionService::detectHackAttempt();
        
        $newLogSize = file_exists($logFile) ? filesize($logFile) : 0;
        $noLogging = $newLogSize === $originalLogSize;

        $securityTests[] = [
            'test' => 'No logging in test mode',
            'passed' => $noLogging,
            'description' => 'System should not log attacks in test mode'
        ];

        $this->testResults['security_tests'] = [
            'total_tests' => count($securityTests),
            'passed_tests' => count(array_filter($securityTests, fn($test) => $test['passed'])),
            'tests' => $securityTests
        ];

        echo "   ✓ Completed " . count($securityTests) . " security tests\n";
    }

    /**
     * Setup test environment
     */
    private function setupTestEnvironment(array $input): void {
        $_GET = $input['get'] ?? [];
        $_POST = $input['post'] ?? [];
        $_COOKIE = $input['cookie'] ?? [];
        $_SERVER = array_merge($_SERVER, $input['server'] ?? []);
        $_FILES = $input['files'] ?? [];
        $_SERVER['HTTP_X_SECURITY_TEST'] = $this->testKey;
    }

    /**
     * Generate comprehensive NoSQL test report
     */
    private function generateNoSQLTestReport(): array {
        $endTime = microtime(true);
        $totalTime = $endTime - $this->startTime;

        $report = [
            'test_summary' => [
                'total_execution_time' => $totalTime,
                'memory_peak_usage' => memory_get_peak_usage(true),
                'test_timestamp' => date('Y-m-d H:i:s'),
                'php_version' => PHP_VERSION,
                'test_mode_verified' => true
            ],
            'detailed_results' => $this->testResults,
            'performance_analysis' => $this->analyzePerformance()
        ];

        // Calculate overall success rate
        $totalTests = 0;
        $passedTests = 0;

        foreach ($this->testResults as $category => $results) {
            if (isset($results['passed_tests']) && isset($results['total_tests'])) {
                $totalTests += $results['total_tests'];
                $passedTests += $results['passed_tests'];
            }
        }

        $report['test_summary']['total_tests'] = $totalTests;
        $report['test_summary']['passed_tests'] = $passedTests;
        $report['test_summary']['success_rate'] = $totalTests > 0 ? ($passedTests / $totalTests) * 100 : 0;

        $this->printNoSQLReport($report);

        return $report;
    }

    /**
     * Analyze performance metrics
     */
    private function analyzePerformance(): array {
        if (empty($this->performanceMetrics)) {
            return [];
        }

        return [
            'average_detection_time' => array_sum($this->performanceMetrics) / count($this->performanceMetrics),
            'min_detection_time' => min($this->performanceMetrics),
            'max_detection_time' => max($this->performanceMetrics),
            'total_detection_time' => array_sum($this->performanceMetrics),
            'detection_count' => count($this->performanceMetrics)
        ];
    }

    /**
     * Print formatted NoSQL test report
     */
    private function printNoSQLReport(array $report): void {
        echo "\n" . str_repeat("=", 70) . "\n";
        echo "NOSQL INJECTION DETECTION TEST REPORT\n";
        echo str_repeat("=", 70) . "\n";

        $summary = $report['test_summary'];
        
        printf("Execution Time: %.3f seconds\n", $summary['total_execution_time']);
        printf("Memory Usage: %.2f MB\n", $summary['memory_peak_usage'] / 1024 / 1024);
        printf("PHP Version: %s\n", $summary['php_version']);
        printf("Total Tests: %d\n", $summary['total_tests']);
        printf("Passed Tests: %d\n", $summary['passed_tests']);
        printf("Success Rate: %.1f%%\n", $summary['success_rate']);

        if (isset($report['performance_analysis']['average_detection_time'])) {
            printf("Avg Detection Time: %.4f seconds\n", $report['performance_analysis']['average_detection_time']);
        }

        echo "\nDETAILED RESULTS:\n";
        echo str_repeat("-", 50) . "\n";

        foreach ($report['detailed_results'] as $category => $results) {
            $categoryName = str_replace('_', ' ', ucfirst($category));
            printf("%-30s: ", $categoryName);

            if (isset($results['passed_tests']) && isset($results['total_tests'])) {
                printf("%d/%d passed", $results['passed_tests'], $results['total_tests']);
                
                if (isset($results['critical_tests'])) {
                    printf(" (%d critical)", $results['critical_tests']);
                }
                echo "\n";
            } else {
                echo "Completed\n";
            }
        }

        echo str_repeat("=", 70) . "\n";

        // Print recommendations
        if ($summary['success_rate'] < 90) {
            echo "RECOMMENDATIONS:\n";
            echo "- Review failed test cases in authentication bypass and code execution\n";
            echo "- Check MongoDB operator pattern matching\n";
            echo "- Verify detection thresholds for different NoSQL databases\n";
            echo "- Consider adding more test cases for edge scenarios\n";
        } else {
            echo "✓ All NoSQL injection tests completed successfully.\n";
            echo "✓ System is effectively detecting NoSQL injection attacks.\n";
            echo "✓ Ready for production deployment.\n";
        }

        echo str_repeat("=", 70) . "\n";
    }

    /**
     * Run specific test category
     */
    public function runSpecificTest(string $testCategory): array {
        switch ($testCategory) {
            case 'patterns':
                $this->testNoSQLPatternValidation();
                break;
            case 'operators':
                $this->testMongoDBOperators();
                break;
            case 'auth':
                $this->testAuthenticationBypass();
                break;
            case 'code':
                $this->testCodeExecution();
                break;
            case 'databases':
                $this->testDatabaseSpecific();
                break;
            case 'falsepositives':
                $this->testFalsePositives();
                break;
            case 'performance':
                $this->testPerformance();
                break;
            case 'security':
                $this->testSecurity();
                break;
            default:
                throw new InvalidArgumentException("Unknown test category: $testCategory");
        }

        return $this->testResults[$testCategory . '_tests'] ?? $this->testResults;
    }

    /**
     * Clean up test environment
     */
    public function cleanup(): void {
        $_GET = $_POST = $_COOKIE = $_FILES = [];
        $_SERVER = array_filter($_SERVER, fn($key) => !str_starts_with($key, 'HTTP_X_SECURITY'), ARRAY_FILTER_USE_KEY);
        $this->testResults = [];
        $this->performanceMetrics = [];
    }
}

// Command line interface
if (php_sapi_name() === 'cli' && basename(__FILE__) === basename($_SERVER['argv'][0] ?? '')) {
    $tester = new NoSQLInjectionTester();
    
    $options = getopt('', ['category:', 'help', 'quick']);
    
    if (isset($options['help'])) {
        echo "NoSQL Injection Detection Tester\n";
        echo "Usage: php NoSQLInjectionTester.php [--category=name] [--quick]\n";
        echo "Categories: patterns, operators, auth, code, databases, falsepositives, performance, security\n";
        echo "Quick mode: Runs only critical tests\n";
        exit(0);
    }
    
    if (isset($options['quick'])) {
        // Run only critical tests
        $tester->runSpecificTest('auth');
        $tester->runSpecificTest('code');
        $result = $tester->generateNoSQLTestReport();
    } elseif (isset($options['category'])) {
        $result = $tester->runSpecificTest($options['category']);
    } else {
        $result = $tester->runAllNoSQLTests();
    }
    
    $tester->cleanup();
    exit($result['test_summary']['success_rate'] >= 90 ? 0 : 1);
}