<?php
declare(strict_types=1);

namespace App\Framework\View;

use App\Framework\Attributes\Singleton;
use App\Framework\Cache\Cache;
use App\Framework\Core\PathProvider;
use App\Framework\DI\Container;
use App\Framework\DI\DefaultContainer;
use App\Framework\Filesystem\FileStorage;
use App\Framework\View\Caching\Analysis\SmartTemplateAnalyzer;
use App\Framework\View\Caching\CacheManager;
use App\Framework\View\Caching\TaggedFragmentCache;
use App\Framework\View\Caching\TemplateContext;
use App\Framework\View\Loading\TemplateLoader;
use App\Framework\View\Processors\CsrfReplaceProcessor;
use Archive\Optimized\QuickSmartCacheReplacement;

#[Singleton]
final readonly class Engine implements TemplateRenderer
{
    private ?TemplateRenderer $smartCache;

    private ?CacheManager $cacheManager;

    public function __construct(
        private TemplateLoader    $loader,
        private PathProvider         $pathProvider,
        private DomTemplateParser $parser = new DomTemplateParser,
        private TemplateProcessor $processor = new TemplateProcessor,
        private FileStorage       $storage = new FileStorage,
        private string            $cachePath = __DIR__ . "/cache",
        private Container        $container = new DefaultContainer(),
        private bool             $useSmartCache = true,
        private bool             $legacyCacheEnabled = false,
        ?Cache                   $cache = null,
        private bool             $cacheEnabled = true,
    ) {
        // Stelle sicher, dass das Cache-Verzeichnis existiert
        if (!is_dir($this->cachePath)) {
            mkdir($this->cachePath, 0755, true);
        }
/*
        // Initialisiere Smart Cache System
        if ($this->useSmartCache && $cache) {
            #$analyzer = new TemplateAnalyzer();
            #$fragmentCache = new FragmentCacheManager($cache);

            $this->smartCache = new QuickSmartCacheReplacement(
                cache: $cache,
                #analyzer     : $analyzer,
                #fragmentCache: $fragmentCache,
                loader: $this->loader,
                processor: $this->processor
            );
        } else {
            $this->smartCache = null;
        }*/

        // Neues Cache-System initialisieren
        if ($this->cacheEnabled && $cache) {
            $analyzer = new SmartTemplateAnalyzer($this->loader);
            $fragmentCache = new TaggedFragmentCache($cache);

            $this->cacheManager = new CacheManager(
                cache: $cache,
                analyzer: $analyzer,
                fragmentCache: $fragmentCache
            );
        } else {
            $this->cacheManager = null;
        }
    }

    public function render(RenderContext $context): string
    {
        // Verwende neuen CacheManager wenn verfügbar
        if ($this->cacheManager) {
            $templateContext = new TemplateContext(
                template: $context->template,
                data: $context->data,
                controllerClass: $context->controllerClass,
                metadata: $context->metaData ? ['meta' => $context->metaData] : []
            );

            return $this->cacheManager->render($templateContext, function() use ($context) {
                return $this->renderDirect($context);
            });
        }

        // Fallback ohne Cache
        return $this->renderDirect($context);


        // Verwende Smart Cache wenn verfügbar
        if ($this->useSmartCache && $this->smartCache !== null) {

            $processor = new TemplateProcessor([],[CsrfReplaceProcessor::class], $this->container);

            $cachedOutput = $this->smartCache->render($context);
            return $processor->render($context, $cachedOutput ?? '');
        }


        // Fallback zu Legacy-Caching oder direkt rendern
        return $this->legacyCacheEnabled
            ? $this->renderWithLegacyCache($context)
            : $this->renderDirect($context);
    }

    private function renderWithLegacyCache(RenderContext $context): string
    {
        $cacheKey = 'view_' . md5($context->template . '_' . ($context->controllerClass ?? ''));
        $templateFile = $this->loader->getTemplatePath($context->template, $context->controllerClass);
        $cacheFile = $this->cachePath . "/{$cacheKey}.cache.html";

        // Prüfe ob Cache existiert und nicht älter als das Template
        // FIXED: Entferne das "x" Suffix um Caching zu reaktivieren
        if (file_exists($cacheFile) && filemtime($cacheFile) >= filemtime($templateFile)) {
            $content = $this->storage->get($cacheFile);
        } else {
            // Template normal laden und kompilieren
            $content = $this->loader->load($context->template, $context->controllerClass, $context);
            $dom = $this->parser->parse($content);
            $html = $dom->saveHTML();

            $html = html_entity_decode($html);
            // VOR dynamischer Verarbeitung rohe Struktur cachen
            $this->storage->put($cacheFile, $html);
            $content = $html;
        }

        return $this->processor->render($context, $content);
    }

    private function renderDirect(RenderContext $context): string
    {
        $content = $this->loader->load($context->template, $context->controllerClass, $context);
        $dom = $this->parser->parse($content);
        $html = html_entity_decode($dom->saveHTML());
        return $this->processor->render($context, $html);
    }

    public function invalidateCache(?string $template = null): int
    {
        return $this->cacheManager?->invalidateTemplate($template) ?? 0;
    }

    public function getCacheStats(): array
    {
        if (!$this->cacheManager) {
            return ['cache_enabled' => false];
        }

        return [
            'cache_enabled' => true,
            'cache_manager' => $this->cacheManager->getStats(), // Diese Methode müsstest du noch implementieren
        ];
    }

}
