<?php

namespace App\Framework\View;

use App\Framework\DI\Container;
use App\Framework\View\Processing\DomProcessingPipeline;
use Dom\HTMLDocument;

final class TemplateProcessor
{
    private array $resolvedProcessors = [];
    public function __construct(
        private readonly array $domProcessors,
        private readonly array $stringProcessors,
        private readonly Container $container
    ) {}

    public function render(RenderContext $context, string $html, bool $component = false): string
    {
        #$dom = $this->processDom($html, $context);

        $domPipeline = new DomProcessingPipeline($this->domProcessors, $this->container->get(ProcessorResolver::class));

        $dom = $domPipeline->process($context, $html);

        $html = $component ? $this->extractBodyContent($dom->document) : $dom->document->saveHTML();
        #$html = $dom->body->innerHTML;

        return $this->processString($html, $context);
    }

    public function __debugInfo(): ?array
    {
        return [
            $this->domProcessors,
            $this->stringProcessors,
        ];
    }

    private function processDom(string $html, RenderContext $context): HTMLDocument
    {
        $parser = new DomTemplateParser();
        $dom = $parser->parse($html);

        // Verkettete Verarbeitung der DOM-Prozessoren
        foreach ($this->domProcessors as $processorClass) {

            $processor = $this->resolveProcessor($processorClass);

            if($processor instanceof EnhancedDomProcessor) {
                $dom = $processor->process(DomWrapper::fromString($dom->saveHtml()), $context)->document;
                #$dom = $dom->document;
            } else {
                $dom = $processor->process($dom, $context);
            }
        }
        return $dom;
    }

    private function processString(string $html, RenderContext $context): string
    {
        // Verarbeitung durch String-Prozessoren
        foreach ($this->stringProcessors as $processorClass) {
            $processor = $this->resolveProcessor($processorClass);
            $html = $processor->process($html, $context);
        }

        return $html;
    }

    public function resolveProcessor(string $processorClass): object
    {
        if (!isset($this->resolvedProcessors[$processorClass])) {
            $this->resolvedProcessors[$processorClass] = $this->container->get($processorClass);;
        }
        return $this->resolvedProcessors[$processorClass];
    }

    private function extractBodyContent(HTMLDocument $dom): string
    {
        return $dom->body?->innerHTML ?? '';
    }
}
