<?php

declare(strict_types=1);

use App\Framework\DI\DefaultContainer;
use App\Framework\Meta\MetaData;
use App\Framework\View\DomWrapper;
use App\Framework\View\Processors\ForProcessor;
use App\Framework\View\Processors\PlaceholderReplacer;
use App\Framework\View\RenderContext;

beforeEach(function () {
    $this->container = new DefaultContainer();
    $this->container->singleton(
        PlaceholderReplacer::class,
        new PlaceholderReplacer($this->container)
    );
    $this->processor = new ForProcessor($this->container);
});

describe('ForProcessor', function () {
    it('processes simple for loops with array data', function () {
        $html = <<<HTML
<ul>
    <for var="item" in="items">
        <li>{{ item.name }}</li>
    </for>
</ul>
HTML;

        $context = new RenderContext(
            template: 'test',
            metaData: new MetaData('Test', 'Test'),
            data: [
                'items' => [
                    ['name' => 'Item 1'],
                    ['name' => 'Item 2'],
                    ['name' => 'Item 3'],
                ],
            ],
            controllerClass: null
        );

        $dom = DomWrapper::fromString($html);
        $result = $this->processor->process($dom, $context);
        $output = $result->toHtml(true);

        expect($output)->toContain('Item 1');
        expect($output)->toContain('Item 2');
        expect($output)->toContain('Item 3');
        expect(str_contains($output, '<for'))->toBeFalse();
    });

    it('processes table rows in for loops', function () {
        $html = <<<HTML
<table>
    <tbody>
        <for var="check" in="health_checks">
            <tr>
                <td>{{ check.componentName }}</td>
                <td>{{ check.status }}</td>
            </tr>
        </for>
    </tbody>
</table>
HTML;

        $context = new RenderContext(
            template: 'health',
            metaData: new MetaData('Health', 'Health'),
            data: [
                'health_checks' => [
                    ['componentName' => 'Database', 'status' => 'healthy'],
                    ['componentName' => 'Cache', 'status' => 'healthy'],
                    ['componentName' => 'Queue', 'status' => 'degraded'],
                ],
            ],
            controllerClass: null
        );

        $dom = DomWrapper::fromString($html);
        $result = $this->processor->process($dom, $context);
        $output = $result->toHtml(true);

        expect($output)->toContain('Database');
        expect($output)->toContain('Cache');
        expect($output)->toContain('Queue');
        expect($output)->toContain('healthy');
        expect($output)->toContain('degraded');
        expect(str_contains($output, '<for'))->toBeFalse();
    });

    it('handles empty arrays gracefully', function () {
        $html = <<<HTML
<ul>
    <for var="item" in="items">
        <li>{{ item.name }}</li>
    </for>
</ul>
HTML;

        $context = new RenderContext(
            template: 'test',
            metaData: new MetaData('Test', 'Test'),
            data: ['items' => []],
            controllerClass: null
        );

        $dom = DomWrapper::fromString($html);
        $result = $this->processor->process($dom, $context);
        $output = $result->toHtml(true);

        expect(str_contains($output, '<for'))->toBeFalse();
        expect(str_contains($output, '{{ item.name }}'))->toBeFalse();
    });

    it('processes nested property paths', function () {
        $html = <<<HTML
<div>
    <for var="user" in="data.users">
        <p>{{ user.profile.displayName }}</p>
    </for>
</div>
HTML;

        $context = new RenderContext(
            template: 'test',
            metaData: new MetaData('Test', 'Test'),
            data: [
                'data' => [
                    'users' => [
                        ['profile' => ['displayName' => 'John Doe']],
                        ['profile' => ['displayName' => 'Jane Smith']],
                    ],
                ],
            ],
            controllerClass: null
        );

        $dom = DomWrapper::fromString($html);
        $result = $this->processor->process($dom, $context);
        $output = $result->toHtml(true);

        expect($output)->toContain('John Doe');
        expect($output)->toContain('Jane Smith');
    });

    it('handles boolean values correctly', function () {
        $html = <<<HTML
<div>
    <for var="item" in="items">
        <span>{{ item.active }}</span>
    </for>
</div>
HTML;

        $context = new RenderContext(
            template: 'test',
            metaData: new MetaData('Test', 'Test'),
            data: [
                'items' => [
                    ['active' => true],
                    ['active' => false],
                ],
            ],
            controllerClass: null
        );

        $dom = DomWrapper::fromString($html);
        $result = $this->processor->process($dom, $context);
        $output = $result->toHtml(true);

        expect($output)->toContain('true');
        expect($output)->toContain('false');
    });
});
