<?php

declare(strict_types=1);

use App\Framework\Discovery\Processing\ClassExtractor;
use App\Framework\Filesystem\File;
use App\Framework\Filesystem\FileSystemService;

beforeEach(function () {
    $this->fileSystem = new FileSystemService();
    $this->extractor = new ClassExtractor($this->fileSystem);
    $this->tmpDir = '/var/www/html/tests/tmp';

    if (! is_dir($this->tmpDir)) {
        mkdir($this->tmpDir, 0777, true);
    }

    $this->createTestFile = function (string $filename, string $content): File {
        $filepath = $this->tmpDir . '/' . $filename;
        file_put_contents($filepath, $content);

        $spl = new SplFileInfo($filepath);

        return File::fromSplFileInfo($spl);
    };
});

afterEach(function () {
    // Clean up test files
    if (is_dir($this->tmpDir)) {
        $files = glob($this->tmpDir . '/*');
        foreach ($files as $file) {
            if (is_file($file)) {
                unlink($file);
            }
        }
    }
});

describe('ClassExtractor', function () {
    it('extracts classes from PHP file', function () {
        $content = <<<'PHP'
<?php

namespace App\Test;

final readonly class TestClass
{
    public function test(): void {}
}
PHP;

        $file = ($this->createTestFile)('TestClass.php', $content);
        $classes = $this->extractor->extractFromFile($file);

        expect($classes)->toHaveCount(1);
        expect($classes[0]->getFullyQualified())->toBe('App\Test\TestClass');
    });

    it('returns empty array for HTML template files without PHP tags', function () {
        $content = <<<'HTML'
<layout name="layouts/main" />

<div class="section">
    <h2>Dashboard</h2>
    <div class="stats-grid">
        <div class="stat-card">
            <h3>Status</h3>
        </div>
    </div>
</div>
HTML;

        $file = ($this->createTestFile)('template.view.php', $content);
        $classes = $this->extractor->extractFromFile($file);

        expect($classes)->toHaveCount(0);
    });

    it('extracts multiple classes from file', function () {
        $content = <<<'PHP'
<?php

namespace App\Test;

interface TestInterface {}

final readonly class TestClass implements TestInterface {}

trait TestTrait {}

enum TestEnum {
    case CASE_ONE;
}
PHP;

        $file = ($this->createTestFile)('Multiple.php', $content);
        $classes = $this->extractor->extractFromFile($file);

        expect($classes)->toHaveCount(4);
    });

    it('handles files with short PHP tags', function () {
        $content = <<<'PHP'
<?= "test" ?>
<?php

class ShortTagTest {}
PHP;

        $file = ($this->createTestFile)('ShortTag.php', $content);
        $classes = $this->extractor->extractFromFile($file);

        expect($classes)->toHaveCount(1);
    });

    it('extracts detailed class information', function () {
        $content = <<<'PHP'
<?php

namespace App\Test;

final readonly class DetailedClass
{
    public function method(): void {}
}
PHP;

        $file = ($this->createTestFile)('Detailed.php', $content);
        $detailed = $this->extractor->extractDetailedFromFile($file);

        expect($detailed)->toHaveCount(1);
        expect($detailed[0]['type'])->toBe('class');
        expect($detailed[0]['name'])->toBe('DetailedClass');
        expect($detailed[0]['namespace'])->toBe('App\Test');
        expect($detailed[0]['fqn'])->toBe('App\Test\DetailedClass');
    });

    it('returns empty array for files with syntax errors', function () {
        $content = <<<'PHP'
<?php

class InvalidClass {
    // Missing closing brace
PHP;

        $file = ($this->createTestFile)('Invalid.php', $content);
        $classes = $this->extractor->extractFromFile($file);

        expect($classes)->toHaveCount(0);
    });

    it('analyzes complete file structure', function () {
        $content = <<<'PHP'
<?php

namespace App\Test;

use App\Framework\Core\Application;

final readonly class AnalysisTest
{
    public function __construct(
        private Application $app
    ) {}
}
PHP;

        $file = ($this->createTestFile)('Analysis.php', $content);
        $analysis = $this->extractor->analyzeFile($file);

        expect($analysis)->toHaveKeys(['classes', 'functions', 'attributes', 'uses']);
        expect($analysis['classes'])->toHaveCount(1);
        expect($analysis['uses'])->toHaveCount(1);
    });

    it('does not extract from pure HTML without PHP tags', function () {
        $content = <<<'HTML'
<!DOCTYPE html>
<html>
<head>
    <title>Test</title>
</head>
<body>
    <div class="container">
        <h1>Title</h1>
    </div>
</body>
</html>
HTML;

        $file = ($this->createTestFile)('pure.html', $content);
        $classes = $this->extractor->extractFromFile($file);

        expect($classes)->toHaveCount(0);
    });
});
