<?php

declare(strict_types=1);

use App\Framework\DI\DefaultContainer;
use App\Framework\Template\Parser\DomTemplateParser;
use App\Framework\View\ComponentRenderer;
use App\Framework\View\DomComponentService;
use App\Framework\View\Processors\ComponentProcessor;
use App\Framework\View\Processors\PlaceholderReplacer;
use App\Framework\View\RenderContext;

beforeEach(function () {
    $this->container = new DefaultContainer();

    // Setup dependencies
    $this->container->singleton(
        PlaceholderReplacer::class,
        new PlaceholderReplacer($this->container)
    );

    $this->componentService = new DomComponentService();
    $this->componentRenderer = new ComponentRenderer(
        __DIR__ . '/../../../src/Framework/View/templates/components'
    );

    $this->processor = new ComponentProcessor(
        $this->componentService,
        $this->componentRenderer,
        $this->container
    );

    $this->parser = new DomTemplateParser();
});

describe('ComponentProcessor', function () {
    it('processes simple component without attributes', function () {
        $html = <<<HTML
<div>
    <component name="alert" />
</div>
HTML;

        $dom = $this->parser->parseToWrapper($html);
        $context = new RenderContext(
            template: 'test',
            data: [
                'type' => 'info',
                'message' => 'Test message',
            ]
        );

        $result = $this->processor->process($dom, $context);
        $output = $result->document->saveHTML();

        expect($output)->toContain('alert alert-info');
        expect($output)->toContain('Test message');
    });

    it('processes component with attributes', function () {
        $html = <<<HTML
<div>
    <component name="alert" type="warning" message="Custom message" />
</div>
HTML;

        $dom = $this->parser->parseToWrapper($html);
        $context = new RenderContext(template: 'test', data: []);

        $result = $this->processor->process($dom, $context);
        $output = $result->document->saveHTML();

        expect($output)->toContain('alert alert-warning');
        expect($output)->toContain('Custom message');
    });

    it('processes nested components', function () {
        $html = <<<HTML
<div>
    <component name="card" title="Test Card" message="Card content" />
</div>
HTML;

        $dom = $this->parser->parseToWrapper($html);
        $context = new RenderContext(template: 'test', data: []);

        $result = $this->processor->process($dom, $context);
        $output = $result->document->saveHTML();

        expect($output)->toContain('card');
        expect($output)->toContain('Test Card');
        expect($output)->toContain('Card content');
    });

    it('handles components with placeholder variables', function () {
        $html = <<<HTML
<div>
    <component name="alert" type="{{ alertType }}" message="{{ alertMessage }}" />
</div>
HTML;

        $dom = $this->parser->parseToWrapper($html);
        $context = new RenderContext(
            template: 'test',
            data: [
                'alertType' => 'success',
                'alertMessage' => 'Operation successful',
            ]
        );

        $result = $this->processor->process($dom, $context);
        $output = $result->document->saveHTML();

        expect($output)->toContain('alert alert-success');
        expect($output)->toContain('Operation successful');
    });

    it('gracefully handles missing component files', function () {
        $html = <<<HTML
<div>
    <component name="non-existent-component" />
</div>
HTML;

        $dom = $this->parser->parseToWrapper($html);
        $context = new RenderContext(template: 'test', data: []);

        // Should not throw exception
        $result = $this->processor->process($dom, $context);

        expect($result)->toBeInstanceOf(App\Framework\View\DomWrapper::class);
    });

    it('processes multiple components in sequence', function () {
        $html = <<<HTML
<div>
    <component name="alert" type="info" message="First alert" />
    <component name="alert" type="warning" message="Second alert" />
    <component name="alert" type="danger" message="Third alert" />
</div>
HTML;

        $dom = $this->parser->parseToWrapper($html);
        $context = new RenderContext(template: 'test', data: []);

        $result = $this->processor->process($dom, $context);
        $output = $result->document->saveHTML();

        expect($output)->toContain('First alert');
        expect($output)->toContain('Second alert');
        expect($output)->toContain('Third alert');
        expect($output)->toContain('alert-info');
        expect($output)->toContain('alert-warning');
        expect($output)->toContain('alert-danger');
    });

    it('skips components without name attribute', function () {
        $html = <<<HTML
<div>
    <component />
    <component name="alert" type="info" message="Valid component" />
</div>
HTML;

        $dom = $this->parser->parseToWrapper($html);
        $context = new RenderContext(template: 'test', data: []);

        $result = $this->processor->process($dom, $context);
        $output = $result->document->saveHTML();

        // Should only process the valid component
        expect($output)->toContain('Valid component');
    });
});
