<?php

declare(strict_types=1);

use App\Framework\Core\ValueObjects\ClassName;

describe('ClassName Edge Cases and Security', function () {

    it('handles potential security issues gracefully', function () {
        // Test with potentially problematic class names that could cause issues
        $dangerousCases = [
            '../../etc/passwd',        // Path traversal attempt
            '<script>alert(1)</script>', // XSS attempt
            'DROP TABLE users',        // SQL injection style
            "\0null\0byte",           // Null byte injection
            'very.long.dotted.name',  // Invalid dots instead of backslashes
        ];

        foreach ($dangerousCases as $dangerous) {
            expect(function () use ($dangerous) {
                ClassName::create($dangerous);
            })->toThrow(InvalidArgumentException::class);
        }
    });

    it('handles unicode and special characters', function () {
        // Some unicode characters are valid in PHP class names (within \x80-\xff range)
        $validUnicodeCase = 'Ñame'; // Accented characters in \x80-\xff range
        $className = ClassName::create($validUnicodeCase);
        expect($className->exists())->toBeFalse(); // Won't exist but should be valid name

        // These should be definitely invalid
        $definitivelyInvalidCases = [
            'Name Space',             // Space (definitely invalid)
            'Name-Dash',              // Dash (definitely invalid)
            'Name.Dot',               // Dot (definitely invalid)
        ];

        foreach ($definitivelyInvalidCases as $invalid) {
            expect(function () use ($invalid) {
                ClassName::create($invalid);
            })->toThrow(InvalidArgumentException::class);
        }

        // Test that we can create valid unicode names without errors
        $potentiallyValidCases = ['Ñame', 'Tëst', 'Clâss'];
        foreach ($potentiallyValidCases as $case) {
            $className = ClassName::create($case);
            expect($className->getFullyQualified())->toBe($case);
            expect($className->exists())->toBeFalse(); // They won't exist but names should be valid
        }
    });

    it('handles very long class names', function () {
        // Test with extremely long but valid class name
        $longNamespace = str_repeat('VeryLongNamespace\\', 50);
        $longClassName = $longNamespace . 'VeryLongClassName';

        $className = ClassName::create($longClassName);
        expect($className->exists())->toBeFalse(); // Should not exist but should not error
        expect($className->getFullyQualified())->toBe($longClassName);
    });

    it('handles constructor edge cases', function () {
        // Test various whitespace and formatting issues
        expect(function () {
            ClassName::create('');
        })->toThrow(InvalidArgumentException::class, 'Class name cannot be empty');

        expect(function () {
            ClassName::create("   \t\n   ");
        })->toThrow(InvalidArgumentException::class);

        // Leading backslashes should be handled correctly (but trailing ones are preserved)
        $className = ClassName::create('\\\\\\App\\Test');
        expect($className->getFullyQualified())->toBe('App\\Test'); // Leading backslashes removed
    });

    it('stress test - handles many rapid exists() calls without issues', function () {
        $startTime = microtime(true);
        $startMemory = memory_get_usage();

        // Rapid fire test
        for ($i = 0; $i < 5000; $i++) {
            $className = ClassName::create('TestClass' . ($i % 100));
            $className->exists();
        }

        $endTime = microtime(true);
        $endMemory = memory_get_usage();

        $duration = $endTime - $startTime;
        $memoryIncrease = $endMemory - $startMemory;

        // Should complete within reasonable time (less than 1 second)
        expect($duration)->toBeLessThan(1.0);

        // Should not consume excessive memory (less than 5MB)
        expect($memoryIncrease)->toBeLessThan(5 * 1024 * 1024);
    });

    it('validates that exists() is consistent across calls', function () {
        // Test that multiple calls to exists() on the same instance return consistent results
        $existingClass = ClassName::create('stdClass');
        $nonExistingClass = ClassName::create('NonExistentClass123');

        // Multiple calls should return the same result
        for ($i = 0; $i < 10; $i++) {
            expect($existingClass->exists())->toBeTrue();
            expect($nonExistingClass->exists())->toBeFalse();
        }

        // Different instances of the same class name should also be consistent
        for ($i = 0; $i < 5; $i++) {
            $newInstance = ClassName::create('stdClass');
            expect($newInstance->exists())->toBeTrue();

            $newNonExisting = ClassName::create('NonExistentClass123');
            expect($newNonExisting->exists())->toBeFalse();
        }
    });

    it('handles the exact scenario from the bug report', function () {
        // This test recreates the exact conditions that caused the original bug:
        // 1. Container compilation process
        // 2. Dependency resolution with potentially empty class names
        // 3. Multiple rapid exists() checks

        $problematicCases = [
            'App\\Framework\\Filesystem\\AtomicStorage',    // The interface that caused issues
            'App\\Framework\\Filesystem\\Storage',         // Parent interface
            'App\\Framework\\Filesystem\\FileStorage',     // Implementation
            'App\\Framework\\DI\\Container',               // Container interface
            'App\\Framework\\DI\\DefaultContainer',        // Container implementation
        ];

        // Simulate rapid container compilation checks
        foreach ($problematicCases as $case) {
            $className = ClassName::create($case);
            $exists = $className->exists();

            // All these should exist and not cause warnings
            expect($exists)->toBeTrue();
            expect($className->getFullyQualified())->toBe($case);
        }

        // Also test with non-existent classes that might be checked during compilation
        $nonExistentCases = [
            'App\\NonExistent\\Interface',
            'App\\Framework\\NonExistent\\Class',
            'Some\\Random\\ClassName\\That\\DoesNot\\Exist',
        ];

        foreach ($nonExistentCases as $case) {
            $className = ClassName::create($case);
            expect($className->exists())->toBeFalse();
        }
    });
});
